TS Revert (1) (#2402)

* revert all commits to before Typescript migration

* update compat workflow to match latest deps (#2335)

* update compat workflow to match latest deps

* attempt to debug

* attempt to debug

* remove debugging code

* typo

* update deps to match desktop (#2340)

* fix: don't run lint with `--fix` on push tests (#2273)

* fix: don't run lint with `--fix` on push tests

* npx

Co-authored-by: maniarathi <mani.arathi@gmail.com>
Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>

* rename X_approx_distribution to X_approximate_distribution (#2337)

* Correctly handle non-finite numbers in heuristic determination of X distribution (#2342)

* handle non-finites explicitly

* improve and test edge case handling for distribution estimation

* revert debugging changes

* code readability

* clean up type inferencing (#2332)

* unit tests for 64 bit conversion

* clean up type handling

* type inference tests

* more type inference fixes

* use schema to determine user intent for data typing

* stop using deprecated API

* fbs type encoding test

* add missing test

* add more tests

* correctly infer X type for CXG adaptor

* lint

* fix typo

* ts migration

* cleanup from PR review

* lint

* PR review changes

* remove unused packages from client (#2359)

* remove unused packages from client

* add missing peer dep

* fix: disable FE auth testing on compatibility tests (#2377)

* update: release process (#2277)

Co-authored-by: maniarathi <mani.arathi@gmail.com>

* fix: remove spaces in param setup (#2380)

* delete deploy workflow (#2396)

* undo reformatting which now does not pass lint

* fix snapshots which changed due to npm dep changes

* add missing quoting to snapshot

* another snapshot typo fix

* TS Revert (2) - replay PR #2347 and #2354 (#2403)

* replay edits from PR 2347

* TS Revert (3) - replay edits in PR #2327 (#2404)

* replay edits in PR 2327

* TS Revert (4) - replay PR #2355 (#2405)

* replay edits in PR 2355

* add additional babel config

* reformat with new prettier config

Co-authored-by: Severiano Badajoz <sbadajoz@chanzuckerberg.com>
Co-authored-by: maniarathi <mani.arathi@gmail.com>
Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
This commit is contained in:
Bruce Martin
2021-08-23 15:01:36 -07:00
committed by GitHub
co-authored by maniarathi Madison Dunitz Severiano Badajoz
parent 295590a7c6
commit eaae6df5e3
253 changed files with 11175 additions and 22271 deletions
+94
View File
@@ -0,0 +1,94 @@
import React from "react";
import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core";
class AnnoDialog extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}
render() {
const {
isActive,
text,
title,
instruction,
cancelTooltipContent,
errorMessage,
validationError,
annoSelect,
annoInput,
secondaryInstructions,
secondaryInput,
handleCancel,
handleSubmit,
primaryButtonText,
secondaryButtonText,
handleSecondaryButtonSubmit,
primaryButtonProps,
} = this.props;
return (
<Dialog icon="tag" title={title} isOpen={isActive} onClose={handleCancel}>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className={Classes.DIALOG_BODY}>
<div style={{ marginBottom: 20 }}>
<p>{instruction}</p>
{annoInput || null}
<p
style={{
marginTop: 7,
visibility: validationError ? "visible" : "hidden",
color: Colors.ORANGE3,
}}
>
{errorMessage}
</p>
{/* we might rename, secondary button and secondary input are not related */}
{secondaryInstructions && (
<p style={{ marginTop: secondaryInstructions ? 20 : 0 }}>
{secondaryInstructions}
</p>
)}
{secondaryInput || null}
</div>
{annoSelect || null}
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Tooltip content={cancelTooltipContent}>
<Button onClick={handleCancel}>Cancel</Button>
</Tooltip>
{/* we might rename, secondary button and secondary input are not related */}
{handleSecondaryButtonSubmit && secondaryButtonText ? (
<Button
onClick={handleSecondaryButtonSubmit}
disabled={!text || validationError}
intent="none"
type="button"
>
{secondaryButtonText}
</Button>
) : null}
<Button
{...primaryButtonProps} // eslint-disable-line react/jsx-props-no-spreading -- Spreading props allows for modularity
onClick={handleSubmit}
disabled={!text || validationError}
intent="primary"
type="submit"
>
{primaryButtonText}
</Button>
</div>
</div>
</form>
</Dialog>
);
}
}
export default AnnoDialog;
-117
View File
@@ -1,117 +0,0 @@
import React from "react";
import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class AnnoDialog extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isActive' does not exist on type 'Readon... Remove this comment to see the full error message
isActive,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'text' does not exist on type 'Readonly<{... Remove this comment to see the full error message
text,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'title' does not exist on type 'Readonly<... Remove this comment to see the full error message
title,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'instruction' does not exist on type 'Rea... Remove this comment to see the full error message
instruction,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cancelTooltipContent' does not exist on ... Remove this comment to see the full error message
cancelTooltipContent,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'errorMessage' does not exist on type 'Re... Remove this comment to see the full error message
errorMessage,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'validationError' does not exist on type ... Remove this comment to see the full error message
validationError,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoSelect' does not exist on type 'Read... Remove this comment to see the full error message
annoSelect,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoInput' does not exist on type 'Reado... Remove this comment to see the full error message
annoInput,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryInstructions' does not exist on... Remove this comment to see the full error message
secondaryInstructions,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryInput' does not exist on type '... Remove this comment to see the full error message
secondaryInput,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCancel' does not exist on type 'Re... Remove this comment to see the full error message
handleCancel,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubmit' does not exist on type 'Re... Remove this comment to see the full error message
handleSubmit,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'primaryButtonText' does not exist on typ... Remove this comment to see the full error message
primaryButtonText,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryButtonText' does not exist on t... Remove this comment to see the full error message
secondaryButtonText,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSecondaryButtonSubmit' does not ex... Remove this comment to see the full error message
handleSecondaryButtonSubmit,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'primaryButtonProps' does not exist on ty... Remove this comment to see the full error message
primaryButtonProps,
} = this.props;
return (
<Dialog icon="tag" title={title} isOpen={isActive} onClose={handleCancel}>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className={Classes.DIALOG_BODY}>
<div style={{ marginBottom: 20 }}>
<p>{instruction}</p>
{annoInput || null}
<p
style={{
marginTop: 7,
visibility: validationError ? "visible" : "hidden",
color: Colors.ORANGE3,
}}
>
{errorMessage}
</p>
{/* we might rename, secondary button and secondary input are not related */}
{secondaryInstructions && (
<p style={{ marginTop: secondaryInstructions ? 20 : 0 }}>
{secondaryInstructions}
</p>
)}
{secondaryInput || null}
</div>
{annoSelect || null}
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Tooltip content={cancelTooltipContent}>
<Button onClick={handleCancel}>Cancel</Button>
</Tooltip>
{/* we might rename, secondary button and secondary input are not related */}
{handleSecondaryButtonSubmit && secondaryButtonText ? (
<Button
onClick={handleSecondaryButtonSubmit}
disabled={!text || validationError}
intent="none"
type="button"
>
{secondaryButtonText}
</Button>
) : null}
<Button
{...primaryButtonProps} // eslint-disable-line react/jsx-props-no-spreading -- Spreading props allows for modularity
onClick={handleSubmit}
disabled={!text || validationError}
intent="primary"
type="submit"
>
{primaryButtonText}
</Button>
</div>
</div>
</form>
</Dialog>
);
}
}
export default AnnoDialog;
@@ -15,38 +15,30 @@ import TermsOfServicePrompt from "./termsPrompt";
import actions from "../actions";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
loading: (state as any).controls.loading,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
error: (state as any).controls.error,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
graphRenderCounter: (state as any).controls.graphRenderCounter,
loading: state.controls.loading,
error: state.controls.error,
graphRenderCounter: state.controls.graphRenderCounter,
}))
class App extends React.Component {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
/* listen for url changes, fire one when we start the app up */
window.addEventListener("popstate", this._onURLChanged);
this._onURLChanged();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
dispatch(actions.doInitialDataLoad(window.location.search));
this.forceUpdate();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_onURLChanged() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({ type: "url changed", url: document.location.href });
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'loading' does not exist on type 'Readonl... Remove this comment to see the full error message
const { loading, error, graphRenderCounter } = this.props;
return (
<Container>
@@ -78,16 +70,13 @@ class App extends React.Component {
{loading || error ? null : (
<Layout>
<LeftSideBar />
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{(viewportRef: any) => (
{(viewportRef) => (
<>
<MenuBar />
<Embedding />
<Autosave />
<TermsOfServicePrompt />
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
<Legend viewportRef={viewportRef} />
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: any; viewportRef: any; }' is not assi... Remove this comment to see the full error message */}
<Graph key={graphRenderCounter} viewportRef={viewportRef} />
</>
)}
@@ -11,78 +11,60 @@ import {
Tooltip,
} from "@blueprintjs/core";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
idhash:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.["annotations-user-data-idhash"] ?? null,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
auth: (state as any).config?.authentication,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userInfo: (state as any).userInfo,
writableCategoriesEnabled:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.annotations ?? false,
idhash: state.config?.parameters?.["annotations-user-data-idhash"] ?? null,
annotations: state.annotations,
auth: state.config?.authentication,
userInfo: state.userInfo,
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false,
writableGenesetsEnabled: !(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
((state as any).config?.parameters?.annotations_genesets_readonly ?? true)
state.config?.parameters?.annotations_genesets_readonly ?? true
),
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class FilenameDialog extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class FilenameDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
filenameText: "",
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
dismissFilenameDialog = () => {};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleCreateFilename = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
const { filenameText } = this.state;
dispatch({
type: "set annotations collection name",
data: filenameText,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
filenameError = () => {
const legalNames = /^\w+$/;
const { filenameText } = this.state;
let err = false;
if (filenameText === "") {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'boolean'.
err = "empty_string";
} else if (!legalNames.test(filenameText)) {
/*
IMPORTANT: this test must ultimately match the test applied by the
backend, which is designed to ensure a safe file name can be created
from the data collection name. If you change this, you will also need
to change the validation code in the backend, or it will have no effect.
*/
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'boolean'.
IMPORTANT: this test must ultimately match the test applied by the
backend, which is designed to ensure a safe file name can be created
from the data collection name. If you change this, you will also need
to change the validation code in the backend, or it will have no effect.
*/
err = "characters";
}
return err;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
filenameErrorMessage = () => {
const err = this.filenameError();
let markup = null;
// @ts-expect-error ts-migrate(2367) FIXME: This condition will always return 'false' since th... Remove this comment to see the full error message
if (err === "empty_string") {
markup = (
<span
@@ -96,7 +78,6 @@ class FilenameDialog extends React.Component<{}, State> {
Name cannot be blank
</span>
);
// @ts-expect-error ts-migrate(2367) FIXME: This condition will always return 'false' since th... Remove this comment to see the full error message
} else if (err === "characters") {
markup = (
<span
@@ -114,21 +95,16 @@ class FilenameDialog extends React.Component<{}, State> {
return markup;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
writableCategoriesEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableGenesetsEnabled' does not exist ... Remove this comment to see the full error message
writableGenesetsEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message
annotations,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'idhash' does not exist on type 'Readonly... Remove this comment to see the full error message
idhash,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'userInfo' does not exist on type 'Readon... Remove this comment to see the full error message
userInfo,
} = this.props;
const { filenameText } = this.state;
return (writableCategoriesEnabled || writableGenesetsEnabled) &&
annotations.promptForFilename &&
!annotations.dataCollectionNameIsReadOnly &&
@@ -152,7 +128,6 @@ class FilenameDialog extends React.Component<{}, State> {
<InputGroup
autoFocus
value={filenameText}
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
intent={this.filenameError(filenameText) ? "warning" : "none"}
onChange={(e) =>
this.setState({ filenameText: e.target.value })
@@ -163,14 +138,12 @@ class FilenameDialog extends React.Component<{}, State> {
<p
style={{
marginTop: 7,
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
visibility: this.filenameError(filenameText)
? "visible"
: "hidden",
color: Colors.ORANGE3,
}}
>
{/* @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. */}
{this.filenameErrorMessage(filenameText)}
</p>
</div>
@@ -198,7 +171,6 @@ class FilenameDialog extends React.Component<{}, State> {
<Button onClick={this.dismissFilenameDialog}>Cancel</Button>
</Tooltip>
<Button
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
disabled={!filenameText || this.filenameError(filenameText)}
onClick={this.handleCreateFilename}
intent="primary"
+122
View File
@@ -0,0 +1,122 @@
import React from "react";
import { connect } from "react-redux";
import actions from "../../actions";
import FilenameDialog from "./filenameDialog";
@connect((state) => ({
annotations: state.annotations,
obsAnnotationSaveInProgress:
state.autosave?.obsAnnotationSaveInProgress ?? false,
genesetSaveInProgress: state.autosave?.genesetSaveInProgress ?? false,
error: state.autosave?.error,
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false,
writableGenesetsEnabled: !(
state.config?.parameters?.annotations_genesets_readonly ?? true
),
annoMatrix: state.annoMatrix,
genesets: state.genesets,
lastSavedAnnoMatrix: state.autosave?.lastSavedAnnoMatrix,
lastSavedGenesets: state.autosave?.lastSavedGenesets,
}))
class Autosave extends React.Component {
constructor(props) {
super(props);
this.state = {
timer: null,
};
}
componentDidMount() {
const { writableCategoriesEnabled, writableGenesetsEnabled } = this.props;
let { timer } = this.state;
if (timer) clearInterval(timer);
if (writableCategoriesEnabled || writableGenesetsEnabled) {
timer = setInterval(this.tick, 2500);
} else {
timer = null;
}
this.setState({ timer });
}
componentWillUnmount() {
const { timer } = this.state;
if (timer) this.clearInterval(timer);
}
tick = () => {
const { dispatch, obsAnnotationSaveInProgress, genesetSaveInProgress } =
this.props;
if (!obsAnnotationSaveInProgress && this.needToSaveObsAnnotations()) {
dispatch(actions.saveObsAnnotationsAction());
}
if (!genesetSaveInProgress && this.needToSaveGenesets()) {
dispatch(actions.saveGenesetsAction());
}
};
needToSaveObsAnnotations = () => {
/* return true if we need to save obs cell labels, false if we don't */
const { annoMatrix, lastSavedAnnoMatrix } = this.props;
return actions.needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix);
};
needToSaveGenesets = () => {
/* return true if we need to save gene ses, false if we do not */
const { genesets, lastSavedGenesets } = this.props;
return genesets.initialized && genesets.genesets !== lastSavedGenesets;
};
needToSave() {
return this.needToSaveGenesets() || this.needToSaveObsAnnotations();
}
saveInProgress() {
const { obsAnnotationSaveInProgress, genesetSaveInProgress } = this.props;
return obsAnnotationSaveInProgress || genesetSaveInProgress;
}
statusMessage() {
const { error } = this.props;
if (error) {
return `Autosave error: ${error}`;
}
return this.needToSave() ? "Unsaved" : "All saved";
}
render() {
const {
writableCategoriesEnabled,
writableGenesetsEnabled,
lastSavedAnnoMatrix,
} = this.props;
const initialDataLoadComplete = lastSavedAnnoMatrix;
if (!writableCategoriesEnabled && !writableGenesetsEnabled) return null;
return (
<div
id="autosave"
data-testclass={
!initialDataLoadComplete
? "autosave-init"
: this.saveInProgress() || this.needToSave()
? "autosave-incomplete"
: "autosave-complete"
}
style={{
position: "absolute",
display: "inherit",
right: 8,
bottom: 8,
zIndex: 1,
}}
>
{this.statusMessage()}
<FilenameDialog />
</div>
);
}
}
export default Autosave;
-160
View File
@@ -1,160 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import actions from "../../actions";
import FilenameDialog from "./filenameDialog";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
obsAnnotationSaveInProgress:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).autosave?.obsAnnotationSaveInProgress ?? false,
genesetSaveInProgress:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).autosave?.genesetSaveInProgress ?? false,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
error: (state as any).autosave?.error,
writableCategoriesEnabled:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.annotations ?? false,
writableGenesetsEnabled: !(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
((state as any).config?.parameters?.annotations_genesets_readonly ?? true)
),
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lastSavedAnnoMatrix: (state as any).autosave?.lastSavedAnnoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lastSavedGenesets: (state as any).autosave?.lastSavedGenesets,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Autosave extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
timer: null,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
const { writableCategoriesEnabled, writableGenesetsEnabled } = this.props;
let { timer } = this.state;
if (timer) clearInterval(timer);
if (writableCategoriesEnabled || writableGenesetsEnabled) {
timer = setInterval(this.tick, 2500);
} else {
timer = null;
}
this.setState({ timer });
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentWillUnmount() {
const { timer } = this.state;
if (timer) clearInterval(timer);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
tick = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsAnnotationSaveInProgress' does not ex... Remove this comment to see the full error message
obsAnnotationSaveInProgress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetSaveInProgress' does not exist on... Remove this comment to see the full error message
genesetSaveInProgress,
} = this.props;
if (!obsAnnotationSaveInProgress && this.needToSaveObsAnnotations()) {
dispatch(actions.saveObsAnnotationsAction());
}
if (!genesetSaveInProgress && this.needToSaveGenesets()) {
dispatch(actions.saveGenesetsAction());
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
needToSaveObsAnnotations = () => {
/* return true if we need to save obs cell labels, false if we don't */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, lastSavedAnnoMatrix } = this.props;
return actions.needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
needToSaveGenesets = () => {
/* return true if we need to save gene ses, false if we do not */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
const { genesets, lastSavedGenesets } = this.props;
return genesets.initialized && genesets.genesets !== lastSavedGenesets;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
needToSave() {
return this.needToSaveGenesets() || this.needToSaveObsAnnotations();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
saveInProgress() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsAnnotationSaveInProgress' does not ex... Remove this comment to see the full error message
const { obsAnnotationSaveInProgress, genesetSaveInProgress } = this.props;
return obsAnnotationSaveInProgress || genesetSaveInProgress;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
statusMessage() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'error' does not exist on type 'Readonly<... Remove this comment to see the full error message
const { error } = this.props;
if (error) {
return `Autosave error: ${error}`;
}
return this.needToSave() ? "Unsaved" : "All saved";
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
writableCategoriesEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableGenesetsEnabled' does not exist ... Remove this comment to see the full error message
writableGenesetsEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'lastSavedAnnoMatrix' does not exist on t... Remove this comment to see the full error message
lastSavedAnnoMatrix,
} = this.props;
const initialDataLoadComplete = lastSavedAnnoMatrix;
if (!writableCategoriesEnabled && !writableGenesetsEnabled) return null;
return (
<div
id="autosave"
data-testclass={
!initialDataLoadComplete
? "autosave-init"
: this.saveInProgress() || this.needToSave()
? "autosave-incomplete"
: "autosave-complete"
}
style={{
position: "absolute",
display: "inherit",
right: 8,
bottom: 8,
zIndex: 1,
}}
>
{this.statusMessage()}
<FilenameDialog />
</div>
);
}
}
export default Autosave;
@@ -0,0 +1,15 @@
import React from "react";
import * as globals from "../../globals";
const ErrorLoading = ({ displayName, zebra }) => (
<div
style={{
backgroundColor: zebra ? globals.lightestGrey : "white",
fontStyle: "italic",
}}
>
<span>{`Failure loading ${displayName}`}</span>
</div>
);
export default ErrorLoading;
@@ -1,16 +0,0 @@
import React from "react";
import * as globals from "../../globals";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
const ErrorLoading = ({ displayName, zebra }: any) => (
<div
style={{
backgroundColor: zebra ? globals.lightestGrey : "white",
fontStyle: "italic",
}}
>
<span>{`Failure loading ${displayName}`}</span>
</div>
);
export default ErrorLoading;
@@ -0,0 +1,63 @@
import React from "react";
const HistogramFooter = React.memo(
({
displayName,
hideRanges,
rangeMin,
rangeMax,
rangeColorMin,
rangeColorMax,
isObs,
isGeneSetSummary,
}) =>
/*
Footer of each histogram. Will render range and title.
Required props:
* displayName - the displayName, aka "n_genes", "FOXP2", etc.
* hideRanges - true/false, enables/disable rendering of ranges
* range - length two array, [min, max], containing the range values to display
* rangeColor - length two array, [mincolor, maxcolor], each a CSS color
*/
(
<div>
<div
style={{
display: "flex",
justifyContent: hideRanges ? "center" : "space-between",
}}
>
<span
style={{
color: rangeColorMin,
display: hideRanges ? "none" : "block",
}}
>
min {rangeMin.toPrecision(4)}
</span>
<span
data-testclass="brushable-histogram-field-name"
style={{ fontStyle: "italic" }}
>
{isObs && displayName}
{isGeneSetSummary && "gene set mean expression"}
</span>
<div style={{ display: hideRanges ? "block" : "none" }}>
: {rangeMin}
</div>
<span
style={{
color: rangeColorMax,
display: hideRanges ? "none" : "block",
}}
>
max {rangeMax.toPrecision(4)}
</span>
</div>
</div>
)
);
export default HistogramFooter;
@@ -1,69 +0,0 @@
import React from "react";
const HistogramFooter = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'displayName' does not exist on type '{ c... Remove this comment to see the full error message
displayName,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'hideRanges' does not exist on type '{ ch... Remove this comment to see the full error message
hideRanges,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'rangeMin' does not exist on type '{ chil... Remove this comment to see the full error message
rangeMin,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'rangeMax' does not exist on type '{ chil... Remove this comment to see the full error message
rangeMax,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'rangeColorMin' does not exist on type '{... Remove this comment to see the full error message
rangeColorMin,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'rangeColorMax' does not exist on type '{... Remove this comment to see the full error message
rangeColorMax,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type '{ childre... Remove this comment to see the full error message
isObs,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isGeneSetSummary' does not exist on type... Remove this comment to see the full error message
isGeneSetSummary,
}) => (
/*
Footer of each histogram. Will render range and title.
Required props:
* displayName - the displayName, aka "n_genes", "FOXP2", etc.
* hideRanges - true/false, enables/disable rendering of ranges
* range - length two array, [min, max], containing the range values to display
* rangeColor - length two array, [mincolor, maxcolor], each a CSS color
*/
<div>
<div
style={{
display: "flex",
justifyContent: hideRanges ? "center" : "space-between",
}}
>
<span
style={{
color: rangeColorMin,
display: hideRanges ? "none" : "block",
}}
>
min {rangeMin.toPrecision(4)}
</span>
<span
data-testclass="brushable-histogram-field-name"
style={{ fontStyle: "italic" }}
>
{isObs && displayName}
{isGeneSetSummary && "gene set mean expression"}
</span>
<div style={{ display: hideRanges ? "block" : "none" }}>
: {rangeMin}
</div>
<span
style={{
color: rangeColorMax,
display: hideRanges ? "none" : "block",
}}
>
max {rangeMax.toPrecision(4)}
</span>
</div>
</div>
)
);
export default HistogramFooter;
@@ -5,23 +5,14 @@ import * as globals from "../../globals";
const HistogramHeader = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'fieldId' does not exist on type '{ child... Remove this comment to see the full error message
fieldId,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorBy' does not exist on type '{ chi... Remove this comment to see the full error message
isColorBy,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onColorByClick' does not exist on type '... Remove this comment to see the full error message
onColorByClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onRemoveClick' does not exist on type '{... Remove this comment to see the full error message
onRemoveClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterPlotX' does not exist on type '... Remove this comment to see the full error message
isScatterPlotX,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterPlotY' does not exist on type '... Remove this comment to see the full error message
isScatterPlotY,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onScatterPlotXClick' does not exist on t... Remove this comment to see the full error message
onScatterPlotXClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onScatterPlotYClick' does not exist on t... Remove this comment to see the full error message
onScatterPlotYClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type '{ childre... Remove this comment to see the full error message
isObs,
}) => {
/*
@@ -2,11 +2,9 @@ import React, { useEffect, useRef, useState } from "react";
import { interpolateCool } from "d3-scale-chromatic";
import * as d3 from "d3";
import { AxisDomain } from "d3";
import maybeScientific from "../../util/maybeScientific";
import clamp from "../../util/clamp";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
const Histogram = ({
field,
fieldForId,
@@ -19,8 +17,8 @@ const Histogram = ({
margin,
isColorBy,
selectionRange,
mini, // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
}: any) => {
mini,
}) => {
const svgRef = useRef(null);
const [brush, setBrush] = useState(null);
@@ -71,19 +69,14 @@ const Histogram = ({
.data(bins)
.enter()
.append("rect")
// @ts-expect-error ts-migrate(6133) FIXME: 'd' is declared but its value is never read.
.attr("x", (d, i) => x(binStart(i)) + 1)
.attr("y", (d) => y(d))
// @ts-expect-error ts-migrate(6133) FIXME: 'd' is declared but its value is never read.
.attr("width", (d, i) => x(binEnd(i)) - x(binStart(i)) - binPadding)
.attr("height", (d) => y(0) - y(d))
.style(
"fill",
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
isColorBy
? // @ts-expect-error ts-migrate(6133) FIXME: 'd' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(d: any, i: any) => colorScale(histogramScale(binStart(i)))
? (d, i) => colorScale(histogramScale(binStart(i)))
: defaultBarColor
);
}
@@ -108,7 +101,6 @@ const Histogram = ({
const brushXselection = container
.insert("g")
.attr("class", "brush")
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
.attr("data-testid", `${svgRef.current.dataset.testid}-brushable-area`)
.call(brushX);
@@ -121,12 +113,7 @@ const Histogram = ({
d3
.axisBottom(x)
.ticks(4)
.tickFormat(
d3.format(maybeScientific(x)) as (
dv: AxisDomain,
i: number
) => string
)
.tickFormat(d3.format(maybeScientific(x)))
);
/* Y AXIS */
@@ -139,10 +126,8 @@ const Histogram = ({
.axisRight(y)
.ticks(3)
.tickFormat(
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
d3.format(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
y.domain().some((n: any) => Math.abs(n) >= 10000) ? ".0e" : ","
y.domain().some((n) => Math.abs(n) >= 10000) ? ".0e" : ","
)
)
);
@@ -152,7 +137,6 @@ const Histogram = ({
svg.selectAll(".axis path").style("stroke", "rgb(230,230,230)");
svg.selectAll(".axis line").style("stroke", "rgb(230,230,230)");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ brushX: d3.BrushBehavior<unkno... Remove this comment to see the full error message
setBrush({ brushX, brushXselection });
}
}, [histogram, isColorBy]);
@@ -162,7 +146,6 @@ const Histogram = ({
paint/update selection brush
*/
if (!brush) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'brushX' does not exist on type 'null'.
const { brushX, brushXselection } = brush;
const selection = d3.brushSelection(brushXselection.node());
if (!selectionRange && selection) {
@@ -179,9 +162,7 @@ const Histogram = ({
} else {
/* there is an active selection and a brush - make sure they match */
const moveDeltaThreshold = 1;
// @ts-expect-error ts-migrate(2363) FIXME: The right-hand side of an arithmetic operation mus... Remove this comment to see the full error message
const dX0 = Math.abs(x0 - selection[0]);
// @ts-expect-error ts-migrate(2363) FIXME: The right-hand side of an arithmetic operation mus... Remove this comment to see the full error message
const dX1 = Math.abs(x1 - selection[1]);
/*
only update the brush if it is grossly incorrect,
@@ -0,0 +1,440 @@
import React from "react";
import { connect, shallowEqual } from "react-redux";
import * as d3 from "d3";
import Async from "react-async";
import memoize from "memoize-one";
import * as globals from "../../globals";
import actions from "../../actions";
import { makeContinuousDimensionName } from "../../util/nameCreators";
import HistogramHeader from "./header";
import Histogram from "./histogram";
import HistogramFooter from "./footer";
import StillLoading from "./loading";
import ErrorLoading from "./error";
const MARGIN = {
LEFT: 10, // Space for 0 tick label on X axis
RIGHT: 54, // space for Y axis & labels
BOTTOM: 25, // space for X axis & labels
TOP: 3,
};
const WIDTH = 340 - MARGIN.LEFT - MARGIN.RIGHT;
const HEIGHT = 135 - MARGIN.TOP - MARGIN.BOTTOM;
const MARGIN_MINI = {
LEFT: 0, // Space for 0 tick label on X axis
RIGHT: 0, // space for Y axis & labels
BOTTOM: 0, // space for X axis & labels
TOP: 0,
};
const WIDTH_MINI = 120 - MARGIN_MINI.LEFT - MARGIN_MINI.RIGHT;
const HEIGHT_MINI = 15 - MARGIN_MINI.TOP - MARGIN_MINI.BOTTOM;
@connect((state, ownProps) => {
const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
const myName = makeContinuousDimensionName(
{ isObs, isUserDefined, isGeneSetSummary },
field
);
return {
annoMatrix: state.annoMatrix,
isScatterplotXXaccessor: state.controls.scatterplotXXaccessor === field,
isScatterplotYYaccessor: state.controls.scatterplotYYaccessor === field,
continuousSelectionRange: state.continuousSelection[myName],
isColorAccessor: state.colors.colorAccessor === field,
};
})
class HistogramBrush extends React.PureComponent {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
/* memoized closure to prevent HistogramHeader unecessary repaint */
handleColorAction = memoize((dispatch) => (field, isObs) => {
if (isObs) {
dispatch({
type: "color by continuous metadata",
colorAccessor: field,
});
} else {
dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(field));
}
});
onBrush = (selection, x, eventType) => {
const type = `continuous metadata histogram ${eventType}`;
return () => {
const { dispatch, field, isObs, isUserDefined, isGeneSetSummary } =
this.props;
// ignore programmatically generated events
if (!d3.event.sourceEvent) return;
// ignore cascading events, which are programmatically generated
if (d3.event.sourceEvent.sourceEvent) return;
const query = this.createQuery();
const range = d3.event.selection
? [x(d3.event.selection[0]), x(d3.event.selection[1])]
: null;
const otherProps = {
selection: field,
continuousNamespace: {
isObs,
isUserDefined,
isGeneSetSummary,
},
};
dispatch(
actions.selectContinuousMetadataAction(type, query, range, otherProps)
);
};
};
onBrushEnd = (selection, x) => () => {
const { dispatch, field, isObs, isUserDefined, isGeneSetSummary } =
this.props;
const minAllowedBrushSize = 10;
const smallAmountToAvoidInfiniteLoop = 0.1;
// ignore programmatically generated events
if (!d3.event.sourceEvent) return;
// ignore cascading events, which are programmatically generated
if (d3.event.sourceEvent.sourceEvent) return;
let type;
let range = null;
if (d3.event.selection) {
type = "continuous metadata histogram end";
if (
d3.event.selection[1] - d3.event.selection[0] >
minAllowedBrushSize
) {
range = [x(d3.event.selection[0]), x(d3.event.selection[1])];
} else {
/* the user selected range is too small and will be hidden #587, so take control of it procedurally */
/* https://stackoverflow.com/questions/12354729/d3-js-limit-size-of-brush */
const procedurallyResizedBrushWidth =
d3.event.selection[0] +
minAllowedBrushSize +
smallAmountToAvoidInfiniteLoop; //
range = [x(d3.event.selection[0]), x(procedurallyResizedBrushWidth)];
}
} else {
type = "continuous metadata histogram cancel";
}
const query = this.createQuery();
const otherProps = {
selection: field,
continuousNamespace: {
isObs,
isUserDefined,
isGeneSetSummary,
},
};
dispatch(
actions.selectContinuousMetadataAction(type, query, range, otherProps)
);
};
handleSetGeneAsScatterplotX = () => {
const { dispatch, field } = this.props;
dispatch({
type: "set scatterplot x",
data: field,
});
};
handleSetGeneAsScatterplotY = () => {
const { dispatch, field } = this.props;
dispatch({
type: "set scatterplot y",
data: field,
});
};
removeHistogram = () => {
const {
dispatch,
field,
isColorAccessor,
isScatterplotXXaccessor,
isScatterplotYYaccessor,
} = this.props;
dispatch({
type: "clear user defined gene",
data: field,
});
if (isColorAccessor) {
dispatch({
type: "reset colorscale",
});
}
if (isScatterplotXXaccessor) {
dispatch({
type: "set scatterplot x",
data: null,
});
}
if (isScatterplotYYaccessor) {
dispatch({
type: "set scatterplot y",
data: null,
});
}
};
fetchAsyncProps = async () => {
const { annoMatrix, width } = this.props;
const { isClipped } = annoMatrix;
const query = this.createQuery();
const df = await annoMatrix.fetch(...query);
const column = df.icol(0);
// if we are clipped, fetch both our value and our unclipped value,
// as we need the absolute min/max range, not just the clipped min/max.
const summary = column.summarize();
const range = [summary.min, summary.max];
let unclippedRange = [...range];
if (isClipped) {
const parent = await annoMatrix.viewOf.fetch(...query);
const { min, max } = parent.icol(0).summarize();
unclippedRange = [min, max];
}
const unclippedRangeColor = [
!annoMatrix.isClipped || annoMatrix.clipRange[0] === 0
? "#bbb"
: globals.blue,
!annoMatrix.isClipped || annoMatrix.clipRange[1] === 1
? "#bbb"
: globals.blue,
];
const histogram = this.calcHistogramCache(
column,
MARGIN,
width || WIDTH,
HEIGHT
);
const miniHistogram = this.calcHistogramCache(
column,
MARGIN_MINI,
width || WIDTH_MINI,
HEIGHT_MINI
);
const isSingleValue = summary.min === summary.max;
const nonFiniteExtent =
summary.min === undefined ||
summary.max === undefined ||
Number.isNaN(summary.min) ||
Number.isNaN(summary.max);
const OK2Render = !summary.categorical && !nonFiniteExtent;
return {
histogram,
miniHistogram,
range,
unclippedRange,
unclippedRangeColor,
isSingleValue,
OK2Render,
};
};
// eslint-disable-next-line class-methods-use-this -- instance method allows for memoization per annotation
calcHistogramCache(col, newMargin, newWidth, newHeight) {
/*
recalculate expensive stuff, notably bins, summaries, etc.
*/
const histogramCache = {}; /* maybe change this so that it computes ... */
const summary =
col.summarize(); /* this is memoized, so it's free the second time you call it */
const { min: domainMin, max: domainMax } = summary;
const numBins = 40;
const { TOP: topMargin, LEFT: leftMargin } =
newMargin; /* changes with mini */
histogramCache.domain = [
domainMin,
domainMax,
]; /* doesn't change with mini */
histogramCache.x = d3
.scaleLinear()
.domain([domainMin, domainMax])
.range([leftMargin, leftMargin + newWidth]);
histogramCache.bins = col.histogram(numBins, [
domainMin,
domainMax,
]); /* memoized */
histogramCache.binWidth = (domainMax - domainMin) / numBins;
histogramCache.binStart = (i) => domainMin + i * histogramCache.binWidth;
histogramCache.binEnd = (i) =>
domainMin + (i + 1) * histogramCache.binWidth;
const yMax = histogramCache.bins.reduce((l, r) => (l > r ? l : r));
histogramCache.y = d3
.scaleLinear()
.domain([0, yMax])
.range([topMargin + newHeight, topMargin]);
return histogramCache;
}
createQuery() {
const { isObs, isGeneSetSummary, field, setGenes, annoMatrix } = this.props;
const { schema } = annoMatrix;
if (isObs) {
return ["obs", field];
}
const varIndex = schema?.annotations?.var?.index;
if (!varIndex) return null;
if (isGeneSetSummary) {
return [
"X",
{
summarize: {
method: "mean",
field: "var",
column: varIndex,
values: [...setGenes.keys()],
},
},
];
}
// else, we assume it is a gene expression
return [
"X",
{
where: {
field: "var",
column: varIndex,
value: field,
},
},
];
}
render() {
const {
dispatch,
annoMatrix,
field,
isColorAccessor,
isUserDefined,
isGeneSetSummary,
isScatterplotXXaccessor,
isScatterplotYYaccessor,
zebra,
continuousSelectionRange,
isObs,
mini,
setGenes,
} = this.props;
let { width } = this.props;
if (!width) {
width = mini ? WIDTH_MINI : WIDTH;
}
const fieldForId = field.replace(/\s/g, "_");
const showScatterPlot = isUserDefined;
let testClass = "histogram-continuous-metadata";
if (isUserDefined) testClass = "histogram-user-gene";
else if (isGeneSetSummary) testClass = "histogram-gene-set-summary";
return (
<Async
watchFn={HistogramBrush.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{ annoMatrix, setGenes }}
>
<Async.Pending initial>
<StillLoading displayName={field} zebra={zebra} />
</Async.Pending>
<Async.Rejected>
{(error) => (
<ErrorLoading zebra={zebra} error={error} displayName={field} />
)}
</Async.Rejected>
<Async.Fulfilled>
{(asyncProps) =>
asyncProps.OK2Render ? (
<div
id={`histogram_${fieldForId}`}
data-testid={`histogram-${field}`}
data-testclass={testClass}
style={{
padding: mini ? 0 : globals.leftSidebarSectionPadding,
backgroundColor: zebra ? globals.lightestGrey : "white",
}}
>
{!mini && isObs ? (
<HistogramHeader
fieldId={field}
isColorBy={isColorAccessor}
isObs={isObs}
onColorByClick={this.handleColorAction(dispatch)}
onRemoveClick={isUserDefined ? this.removeHistogram : null}
isScatterPlotX={isScatterplotXXaccessor}
isScatterPlotY={isScatterplotYYaccessor}
onScatterPlotXClick={
showScatterPlot ? this.handleSetGeneAsScatterplotX : null
}
onScatterPlotYClick={
showScatterPlot ? this.handleSetGeneAsScatterplotY : null
}
/>
) : null}
<Histogram
field={field}
fieldForId={fieldForId}
display={asyncProps.isSingleValue ? "none" : "block"}
histogram={
mini ? asyncProps.miniHistogram : asyncProps.histogram
}
width={width}
height={mini ? HEIGHT_MINI : HEIGHT}
onBrush={this.onBrush}
onBrushEnd={this.onBrushEnd}
margin={mini ? MARGIN_MINI : MARGIN}
isColorBy={isColorAccessor}
selectionRange={continuousSelectionRange}
mini={mini}
/>
{!mini && (
<HistogramFooter
isGeneSetSummary={isGeneSetSummary}
isObs={isObs}
displayName={field}
hideRanges={asyncProps.isSingleValue}
rangeMin={asyncProps.unclippedRange[0]}
rangeMax={asyncProps.unclippedRange[1]}
rangeColorMin={asyncProps.unclippedRangeColor[0]}
rangeColorMax={asyncProps.unclippedRangeColor[1]}
/>
)}
</div>
) : null
}
</Async.Fulfilled>
</Async>
);
}
}
export default HistogramBrush;
@@ -1,547 +0,0 @@
import React from "react";
import { connect, shallowEqual } from "react-redux";
import * as d3 from "d3";
import Async from "react-async";
import memoize from "memoize-one";
import * as globals from "../../globals";
import actions from "../../actions";
import { makeContinuousDimensionName } from "../../util/nameCreators";
import HistogramHeader from "./header";
import Histogram from "./histogram";
import HistogramFooter from "./footer";
import StillLoading from "./loading";
import ErrorLoading from "./error";
import { Dataframe } from "../../util/dataframe";
const MARGIN = {
LEFT: 10, // Space for 0 tick label on X axis
RIGHT: 54, // space for Y axis & labels
BOTTOM: 25, // space for X axis & labels
TOP: 3,
};
const WIDTH = 340 - MARGIN.LEFT - MARGIN.RIGHT;
const HEIGHT = 135 - MARGIN.TOP - MARGIN.BOTTOM;
const MARGIN_MINI = {
LEFT: 0, // Space for 0 tick label on X axis
RIGHT: 0, // space for Y axis & labels
BOTTOM: 0, // space for X axis & labels
TOP: 0,
};
const WIDTH_MINI = 120 - MARGIN_MINI.LEFT - MARGIN_MINI.RIGHT;
const HEIGHT_MINI = 15 - MARGIN_MINI.TOP - MARGIN_MINI.BOTTOM;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state, ownProps) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type '{}'.
const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
const myName = makeContinuousDimensionName(
{ isObs, isUserDefined, isGeneSetSummary },
field
);
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
isScatterplotXXaccessor:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).controls.scatterplotXXaccessor === field,
isScatterplotYYaccessor:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).controls.scatterplotYYaccessor === field,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
continuousSelectionRange: (state as any).continuousSelection[myName],
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
isColorAccessor: (state as any).colors.colorAccessor === field,
};
})
class HistogramBrush extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
/* memoized closure to prevent HistogramHeader unecessary repaint */
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
handleColorAction = memoize((dispatch) => (field: any, isObs: any) => {
if (isObs) {
dispatch({
type: "color by continuous metadata",
colorAccessor: field,
});
} else {
dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(field));
}
});
// @ts-expect-error ts-migrate(6133) FIXME: 'selection' is declared but its value is never rea... Remove this comment to see the full error message
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
onBrush = (selection: any, x: any, eventType: any) => {
const type = `continuous metadata histogram ${eventType}`;
return () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'field' does not exist on type 'Readonly<... Remove this comment to see the full error message
field,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type 'Readonly<... Remove this comment to see the full error message
isObs,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserDefined' does not exist on type 'R... Remove this comment to see the full error message
isUserDefined,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isGeneSetSummary' does not exist on type... Remove this comment to see the full error message
isGeneSetSummary,
} = this.props;
// ignore programmatically generated events
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if (!(d3 as any).event.sourceEvent) return;
// ignore cascading events, which are programmatically generated
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if ((d3 as any).event.sourceEvent.sourceEvent) return;
const query = this.createQuery();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const range = (d3 as any).event.selection
? // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
[x((d3 as any).event.selection[0]), x((d3 as any).event.selection[1])]
: null;
const otherProps = {
selection: field,
continuousNamespace: {
isObs,
isUserDefined,
isGeneSetSummary,
},
};
dispatch(
actions.selectContinuousMetadataAction(type, query, range, otherProps)
);
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
onBrushEnd =
(
_selection: any, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
x: any // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
) =>
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
() => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'field' does not exist on type 'Readonly<... Remove this comment to see the full error message
field,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type 'Readonly<... Remove this comment to see the full error message
isObs,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserDefined' does not exist on type 'R... Remove this comment to see the full error message
isUserDefined,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isGeneSetSummary' does not exist on type... Remove this comment to see the full error message
isGeneSetSummary,
} = this.props;
const minAllowedBrushSize = 10;
const smallAmountToAvoidInfiniteLoop = 0.1;
// ignore programmatically generated events
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if (!(d3 as any).event.sourceEvent) return;
// ignore cascading events, which are programmatically generated
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if ((d3 as any).event.sourceEvent.sourceEvent) return;
let type;
let range = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if ((d3 as any).event.selection) {
type = "continuous metadata histogram end";
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(d3 as any).event.selection[1] - (d3 as any).event.selection[0] >
minAllowedBrushSize
) {
range = [
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
x((d3 as any).event.selection[0]),
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
x((d3 as any).event.selection[1]),
];
} else {
/* the user selected range is too small and will be hidden #587, so take control of it procedurally */
/* https://stackoverflow.com/questions/12354729/d3-js-limit-size-of-brush */
const procedurallyResizedBrushWidth =
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(d3 as any).event.selection[0] +
minAllowedBrushSize +
smallAmountToAvoidInfiniteLoop; //
range = [
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
x((d3 as any).event.selection[0]),
x(procedurallyResizedBrushWidth),
];
}
} else {
type = "continuous metadata histogram cancel";
}
const query = this.createQuery();
const otherProps = {
selection: field,
continuousNamespace: {
isObs,
isUserDefined,
isGeneSetSummary,
},
};
dispatch(
actions.selectContinuousMetadataAction(type, query, range, otherProps)
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSetGeneAsScatterplotX = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, field } = this.props;
dispatch({
type: "set scatterplot x",
data: field,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSetGeneAsScatterplotY = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, field } = this.props;
dispatch({
type: "set scatterplot y",
data: field,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
removeHistogram = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'field' does not exist on type 'Readonly<... Remove this comment to see the full error message
field,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor,
} = this.props;
dispatch({
type: "clear user defined gene",
data: field,
});
if (isColorAccessor) {
dispatch({
type: "reset colorscale",
});
}
if (isScatterplotXXaccessor) {
dispatch({
type: "set scatterplot x",
data: null,
});
}
if (isScatterplotYYaccessor) {
dispatch({
type: "set scatterplot y",
data: null,
});
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, width } = this.props;
const { isClipped } = annoMatrix;
const query = this.createQuery();
// @ts-expect-error ts-migrate(2488) FIXME: Type 'any[] | null' must have a '[Symbol.iterator]... Remove this comment to see the full error message
const df: Dataframe = await annoMatrix.fetch(...query);
const column = df.icol(0);
// if we are clipped, fetch both our value and our unclipped value,
// as we need the absolute min/max range, not just the clipped min/max.
const summary = column.summarizeContinuous();
const range = [summary.min, summary.max];
let unclippedRange = [...range];
if (isClipped) {
const parent: Dataframe = await annoMatrix.viewOf.fetch(...query);
const { min, max } = parent.icol(0).summarizeContinuous();
unclippedRange = [min, max];
}
const unclippedRangeColor = [
!annoMatrix.isClipped || annoMatrix.clipRange[0] === 0
? "#bbb"
: globals.blue,
!annoMatrix.isClipped || annoMatrix.clipRange[1] === 1
? "#bbb"
: globals.blue,
];
const histogram = this.calcHistogramCache(
column,
MARGIN,
width || WIDTH,
HEIGHT
);
const miniHistogram = this.calcHistogramCache(
column,
MARGIN_MINI,
width || WIDTH_MINI,
HEIGHT_MINI
);
const isSingleValue = summary.min === summary.max;
const nonFiniteExtent =
summary.min === undefined ||
summary.max === undefined ||
Number.isNaN(summary.min) ||
Number.isNaN(summary.max);
const OK2Render = !summary.categorical && !nonFiniteExtent;
return {
histogram,
miniHistogram,
range,
unclippedRange,
unclippedRangeColor,
isSingleValue,
OK2Render,
};
};
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- instance method allows for memoization per annotation
calcHistogramCache(col: any, newMargin: any, newWidth: any, newHeight: any) {
/*
recalculate expensive stuff, notably bins, summaries, etc.
*/
const histogramCache = {}; /* maybe change this so that it computes ... */
const summary =
col.summarizeContinuous(); /* this is memoized, so it's free the second time you call it */
const { min: domainMin, max: domainMax } = summary;
const numBins = 40;
const { TOP: topMargin, LEFT: leftMargin } = newMargin;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(histogramCache as any).domain = [domainMin, domainMax];
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
/* doesn't change with mini */ (histogramCache as any).x = d3
.scaleLinear()
.domain([domainMin, domainMax])
.range([leftMargin, leftMargin + newWidth]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(histogramCache as any).bins = col.histogramContinuous(numBins, [
domainMin,
domainMax,
]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
/* memoized */ (histogramCache as any).binWidth =
(domainMax - domainMin) / numBins;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(histogramCache as any).binStart = (i: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
domainMin + i * (histogramCache as any).binWidth;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(histogramCache as any).binEnd = (i: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
domainMin + (i + 1) * (histogramCache as any).binWidth;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const yMax = (histogramCache as any).bins.reduce((l: any, r: any) =>
l > r ? l : r
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(histogramCache as any).y = d3
.scaleLinear()
.domain([0, yMax])
.range([topMargin + newHeight, topMargin]);
return histogramCache;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
createQuery() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type 'Readonly<... Remove this comment to see the full error message
const { isObs, isGeneSetSummary, field, setGenes, annoMatrix } = this.props;
const { schema } = annoMatrix;
if (isObs) {
return ["obs", field];
}
const varIndex = schema?.annotations?.var?.index;
if (!varIndex) return null;
if (isGeneSetSummary) {
return [
"X",
{
summarize: {
method: "mean",
field: "var",
column: varIndex,
values: [...setGenes.keys()],
},
},
];
}
// else, we assume it is a gene expression
return [
"X",
{
where: {
field: "var",
column: varIndex,
value: field,
},
},
];
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'field' does not exist on type 'Readonly<... Remove this comment to see the full error message
field,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserDefined' does not exist on type 'R... Remove this comment to see the full error message
isUserDefined,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isGeneSetSummary' does not exist on type... Remove this comment to see the full error message
isGeneSetSummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'zebra' does not exist on type 'Readonly<... Remove this comment to see the full error message
zebra,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'continuousSelectionRange' does not exist... Remove this comment to see the full error message
continuousSelectionRange,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type 'Readonly<... Remove this comment to see the full error message
isObs,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'mini' does not exist on type 'Readonly<{... Remove this comment to see the full error message
mini,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'setGenes' does not exist on type 'Readon... Remove this comment to see the full error message
setGenes,
} = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
let { width } = this.props;
if (!width) {
width = mini ? WIDTH_MINI : WIDTH;
}
const fieldForId = field.replace(/\s/g, "_");
const showScatterPlot = isUserDefined;
let testClass = "histogram-continuous-metadata";
if (isUserDefined) testClass = "histogram-user-gene";
else if (isGeneSetSummary) testClass = "histogram-gene-set-summary";
return (
<Async
watchFn={HistogramBrush.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{ annoMatrix, setGenes }}
>
<Async.Pending initial>
<StillLoading displayName={field} zebra={zebra} />
</Async.Pending>
<Async.Rejected>
{(error) => (
<ErrorLoading zebra={zebra} error={error} displayName={field} />
)}
</Async.Rejected>
<Async.Fulfilled>
{(asyncProps) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(asyncProps as any).OK2Render ? (
<div
id={`histogram_${fieldForId}`}
data-testid={`histogram-${field}`}
data-testclass={testClass}
style={{
padding: mini ? 0 : globals.leftSidebarSectionPadding,
backgroundColor: zebra ? globals.lightestGrey : "white",
}}
>
{!mini && isObs ? (
<HistogramHeader
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ fieldId: any; isColorBy: any; isObs: any; ... Remove this comment to see the full error message
fieldId={field}
isColorBy={isColorAccessor}
isObs={isObs}
onColorByClick={this.handleColorAction(dispatch)}
onRemoveClick={isUserDefined ? this.removeHistogram : null}
isScatterPlotX={isScatterplotXXaccessor}
isScatterPlotY={isScatterplotYYaccessor}
onScatterPlotXClick={
showScatterPlot ? this.handleSetGeneAsScatterplotX : null
}
onScatterPlotYClick={
showScatterPlot ? this.handleSetGeneAsScatterplotY : null
}
/>
) : null}
<Histogram
field={field}
fieldForId={fieldForId}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
display={(asyncProps as any).isSingleValue ? "none" : "block"}
histogram={
mini
? // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(asyncProps as any).miniHistogram
: // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(asyncProps as any).histogram
}
width={width}
height={mini ? HEIGHT_MINI : HEIGHT}
onBrush={this.onBrush}
onBrushEnd={this.onBrushEnd}
margin={mini ? MARGIN_MINI : MARGIN}
isColorBy={isColorAccessor}
selectionRange={continuousSelectionRange}
mini={mini}
/>
{!mini && (
<HistogramFooter
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isGeneSetSummary: any; isObs: any; display... Remove this comment to see the full error message
isGeneSetSummary={isGeneSetSummary}
isObs={isObs}
displayName={field}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
hideRanges={(asyncProps as any).isSingleValue}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
rangeMin={(asyncProps as any).unclippedRange[0]}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
rangeMax={(asyncProps as any).unclippedRange[1]}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
rangeColorMin={(asyncProps as any).unclippedRangeColor[0]}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
rangeColorMax={(asyncProps as any).unclippedRangeColor[1]}
/>
)}
</div>
) : null
}
</Async.Fulfilled>
</Async>
);
}
}
export default HistogramBrush;
@@ -0,0 +1,43 @@
import React from "react";
import { Button } from "@blueprintjs/core";
import * as globals from "../../globals";
const StillLoading = ({ zebra, displayName }) =>
/*
Render a loading indicator for the field.
*/
(
<div
data-testclass="gene-loading-spinner"
style={{
padding: globals.leftSidebarSectionPadding,
backgroundColor: zebra ? globals.lightestGrey : "white",
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
justifyItems: "center",
alignItems: "center",
}}
>
<div style={{ minWidth: 30 }} />
<div style={{ display: "flex", alignSelf: "center" }}>
<span style={{ fontStyle: "italic" }}>{displayName}</span>
</div>
<div
style={{
display: "flex",
justifyContent: "flex-end",
}}
>
<Button minimal loading intent="primary" />
</div>
</div>
</div>
)
;
export default StillLoading;
@@ -1,41 +0,0 @@
import React from "react";
import { Button } from "@blueprintjs/core";
import * as globals from "../../globals";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
const StillLoading = ({ zebra, displayName }: any) => (
/*
Render a loading indicator for the field.
*/
<div
data-testclass="gene-loading-spinner"
style={{
padding: globals.leftSidebarSectionPadding,
backgroundColor: zebra ? globals.lightestGrey : "white",
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
justifyItems: "center",
alignItems: "center",
}}
>
<div style={{ minWidth: 30 }} />
<div style={{ display: "flex", alignSelf: "center" }}>
<span style={{ fontStyle: "italic" }}>{displayName}</span>
</div>
<div
style={{
display: "flex",
justifyContent: "flex-end",
}}
>
<Button minimal loading intent="primary" />
</div>
</div>
</div>
);
export default StillLoading;
@@ -0,0 +1,54 @@
import React from "react";
import { Button, MenuItem } from "@blueprintjs/core";
import { Select } from "@blueprintjs/select";
class DuplicateCategorySelect extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}
render() {
const {
allCategoryNames,
categoryToDuplicate,
handleModalDuplicateCategorySelection,
} = this.props;
return (
<div>
<p>
Optionally duplicate all labels & cell assignments from existing
category into new category:
</p>
<Select
items={
allCategoryNames ||
[] /* this is a placeholder, could be a subcomponent to avoid this */
}
filterable={false}
itemRenderer={(d, { handleClick }) => (
<MenuItem
data-testclass="duplicate-category-dropdown-option"
onClick={handleClick}
key={d}
text={d}
/>
)}
noResults={<MenuItem disabled text="No results." />}
onItemSelect={(d) => {
handleModalDuplicateCategorySelection(d);
}}
>
{/* children become the popover target; render value here */}
<Button
data-testid="duplicate-category-dropdown"
text={categoryToDuplicate || "None (all cells 'unassigned')"}
rightIcon="double-caret-vertical"
/>
</Select>
</div>
);
}
}
export default DuplicateCategorySelect;
@@ -1,65 +0,0 @@
import React from "react";
import { Button, MenuItem } from "@blueprintjs/core";
import { Select } from "@blueprintjs/select";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class DuplicateCategorySelect extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'allCategoryNames' does not exist on type... Remove this comment to see the full error message
allCategoryNames,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryToDuplicate' does not exist on t... Remove this comment to see the full error message
categoryToDuplicate,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleModalDuplicateCategorySelection' d... Remove this comment to see the full error message
handleModalDuplicateCategorySelection,
} = this.props;
return (
<div>
<p>
Optionally duplicate all labels & cell assignments from existing
category into new category:
</p>
<Select
items={
allCategoryNames ||
[] /* this is a placeholder, could be a subcomponent to avoid this */
}
filterable={false}
itemRenderer={(d, { handleClick }) => (
<MenuItem
data-testclass="duplicate-category-dropdown-option"
onClick={handleClick}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'Key | nu... Remove this comment to see the full error message
key={d}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'ReactNod... Remove this comment to see the full error message
text={d}
/>
)}
noResults={<MenuItem disabled text="No results." />}
onItemSelect={(d) => {
handleModalDuplicateCategorySelection(d);
}}
>
{/* children become the popover target; render value here */}
<Button
data-testid="duplicate-category-dropdown"
text={categoryToDuplicate || "None (all cells 'unassigned')"}
rightIcon="double-caret-vertical"
/>
</Select>
</div>
);
}
}
export default DuplicateCategorySelect;
@@ -0,0 +1,113 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import { labelPrompt, isLabelErroneous } from "../labelUtil";
import actions from "../../../actions";
@connect((state) => ({
annotations: state.annotations,
schema: state.annoMatrix?.schema,
obsCrossfilter: state.obsCrossfilter,
}))
class Category extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
newLabelText: "",
};
}
disableAddNewLabelMode = (e) => {
const { dispatch } = this.props;
this.setState({
newLabelText: "",
});
dispatch({
type: "annotation: disable add new label mode",
});
if (e) e.preventDefault();
};
handleAddNewLabelToCategory = (e) => {
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
this.disableAddNewLabelMode();
dispatch(
actions.annotationCreateLabelInCategory(
metadataField,
newLabelText,
false
)
);
e.preventDefault();
};
addLabelAndAssignCells = (e) => {
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
this.disableAddNewLabelMode();
dispatch(
actions.annotationCreateLabelInCategory(metadataField, newLabelText, true)
);
e.preventDefault();
};
labelNameError = (name) => {
const { metadataField, schema } = this.props;
return isLabelErroneous(name, metadataField, schema);
};
instruction = (label) => labelPrompt(this.labelNameError(label), "New, unique label", ":");
handleChangeOrSelect = (label) => {
this.setState({ newLabelText: label });
};
render() {
const { newLabelText } = this.state;
const { metadataField, annotations, obsCrossfilter } = 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={this.instruction(newLabelText)}
cancelTooltipContent="Close this dialog without adding a label."
primaryButtonText="Add label"
secondaryButtonText={`Add label & assign ${obsCrossfilter.countSelected()} selected cells`}
handleSecondaryButtonSubmit={this.addLabelAndAssignCells}
text={newLabelText}
validationError={this.labelNameError(newLabelText)}
handleSubmit={this.handleAddNewLabelToCategory}
handleCancel={this.disableAddNewLabelMode}
annoInput={
<LabelInput
labelSuggestions={null}
onChange={this.handleChangeOrSelect}
onSelect={this.handleChangeOrSelect}
inputProps={{
"data-testid": `${metadataField}:new-label-name`,
leftIcon: "tag",
intent: "none",
autoFocus: true,
}}
/>
}
/>
</>
);
}
}
export default Category;
@@ -1,136 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import { labelPrompt, isLabelErroneous } from "../labelUtil";
import actions from "../../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
obsCrossfilter: (state as any).obsCrossfilter,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Category extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
newLabelText: "",
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
disableAddNewLabelMode = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
this.setState({
newLabelText: "",
});
dispatch({
type: "annotation: disable add new label mode",
});
if (e) e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleAddNewLabelToCategory = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
this.disableAddNewLabelMode();
dispatch(
actions.annotationCreateLabelInCategory(
metadataField,
newLabelText,
false
)
);
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
addLabelAndAssignCells = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
this.disableAddNewLabelMode();
dispatch(
actions.annotationCreateLabelInCategory(metadataField, newLabelText, true)
);
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
labelNameError = (name: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
const { metadataField, schema } = this.props;
return isLabelErroneous(name, metadataField, schema);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
instruction = (label: any) =>
labelPrompt(this.labelNameError(label), "New, unique label", ":");
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChangeOrSelect = (label: any) => {
this.setState({ newLabelText: label });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { newLabelText } = this.state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
const { metadataField, annotations, obsCrossfilter } = this.props;
return (
<>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; inputProps: { "data-testid"... Remove this comment to see the full error message
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={this.instruction(newLabelText)}
cancelTooltipContent="Close this dialog without adding a label."
primaryButtonText="Add label"
secondaryButtonText={`Add label & assign ${obsCrossfilter.countSelected()} selected cells`}
handleSecondaryButtonSubmit={this.addLabelAndAssignCells}
text={newLabelText}
validationError={this.labelNameError(newLabelText)}
handleSubmit={this.handleAddNewLabelToCategory}
handleCancel={this.disableAddNewLabelMode}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ labelSuggestions: null; onChange: (label: ... Remove this comment to see the full error message
labelSuggestions={null}
onChange={this.handleChangeOrSelect}
onSelect={this.handleChangeOrSelect}
inputProps={{
"data-testid": `${metadataField}:new-label-name`,
leftIcon: "tag",
intent: "none",
autoFocus: true,
}}
/>
}
/>
</>
);
}
}
export default Category;
@@ -0,0 +1,149 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import { labelPrompt } from "../labelUtil";
import { AnnotationsHelpers } from "../../../util/stateManager";
import actions from "../../../actions";
@connect((state) => ({
annotations: state.annotations,
schema: state.annoMatrix?.schema,
}))
class AnnoDialogEditCategoryName extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
newCategoryText: props.metadataField,
};
}
handleChangeOrSelect = (name) => {
this.setState({
newCategoryText: name,
});
};
disableEditCategoryMode = () => {
const { dispatch, metadataField } = this.props;
dispatch({
type: "annotation: disable category edit mode",
});
this.setState({ newCategoryText: metadataField });
};
handleEditCategory = (e) => {
const { dispatch, metadataField } = this.props;
const { newCategoryText } = this.state;
/*
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
const { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name);
if (
(allCategoryNames.indexOf(newCategoryText) > -1 &&
newCategoryText !== metadataField) ||
newCategoryText === ""
) {
return;
}
this.disableEditCategoryMode();
if (metadataField !== newCategoryText)
dispatch(
actions.annotationRenameCategoryAction(metadataField, newCategoryText)
);
e.preventDefault();
};
editedCategoryNameError = (name) => {
const { metadataField } = this.props;
/* check for syntax errors in category name */
const error = AnnotationsHelpers.annotationNameIsErroneous(name);
if (error) {
return error;
}
/* check for duplicative categories */
/*
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
const { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name);
const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1;
const sameName = name === metadataField;
if (categoryNameAlreadyExists && !sameName) {
return "duplicate";
}
/* otherwise, no error */
return false;
};
instruction = (name) => labelPrompt(
this.editedCategoryNameError(name),
"New, unique category name",
":"
);
allCategoryNames() {
const { schema } = this.props;
return schema.annotations.obs.columns.map((c) => c.name);
}
render() {
const { newCategoryText } = this.state;
const { metadataField, annotations } = this.props;
return (
<>
<AnnoDialog
isActive={
annotations.isEditingCategoryName &&
annotations.categoryBeingEdited === metadataField
}
inputProps={{
"data-testid": `${metadataField}:edit-category-name-dialog`,
}}
primaryButtonProps={{
"data-testid": `${metadataField}:submit-category-edit`,
}}
title="Edit category name"
instruction={this.instruction(newCategoryText)}
cancelTooltipContent="Close this dialog without editing this category."
primaryButtonText="Edit category name"
text={newCategoryText}
validationError={this.editedCategoryNameError(newCategoryText)}
handleSubmit={this.handleEditCategory}
handleCancel={this.disableEditCategoryMode}
annoInput={
<LabelInput
label={newCategoryText}
labelSuggestions={null}
onChange={this.handleChangeOrSelect}
onSelect={this.handleChangeOrSelect}
inputProps={{
"data-testid": `${metadataField}:edit-category-name-text`,
leftIcon: "tag",
intent: "none",
autoFocus: true,
}}
newLabelMessage="New category"
/>
}
/>
</>
);
}
}
export default AnnoDialogEditCategoryName;
@@ -1,172 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import { labelPrompt } from "../labelUtil";
import { AnnotationsHelpers } from "../../../util/stateManager";
import actions from "../../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class AnnoDialogEditCategoryName extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
newCategoryText: props.metadataField,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChangeOrSelect = (name: any) => {
this.setState({
newCategoryText: name,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
disableEditCategoryMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch({
type: "annotation: disable category edit mode",
});
this.setState({ newCategoryText: metadataField });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleEditCategory = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
const { newCategoryText } = this.state;
/*
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
const { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(c: any) => c.name
);
if (
(allCategoryNames.indexOf(newCategoryText) > -1 &&
newCategoryText !== metadataField) ||
newCategoryText === ""
) {
return;
}
this.disableEditCategoryMode();
if (metadataField !== newCategoryText)
dispatch(
actions.annotationRenameCategoryAction(metadataField, newCategoryText)
);
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
editedCategoryNameError = (name: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
const { metadataField } = this.props;
/* check for syntax errors in category name */
const error = AnnotationsHelpers.annotationNameIsErroneous(name);
if (error) {
return error;
}
/* check for duplicative categories */
/*
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
const { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(c: any) => c.name
);
const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1;
const sameName = name === metadataField;
if (categoryNameAlreadyExists && !sameName) {
return "duplicate";
}
/* otherwise, no error */
return false;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
instruction = (name: any) =>
labelPrompt(
this.editedCategoryNameError(name),
"New, unique category name",
":"
);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
allCategoryNames() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
const { schema } = this.props;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
return schema.annotations.obs.columns.map((c: any) => c.name);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { newCategoryText } = this.state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
const { metadataField, annotations } = this.props;
return (
<>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; inputProps: { "data-testid"... Remove this comment to see the full error message
isActive={
annotations.isEditingCategoryName &&
annotations.categoryBeingEdited === metadataField
}
inputProps={{
"data-testid": `${metadataField}:edit-category-name-dialog`,
}}
primaryButtonProps={{
"data-testid": `${metadataField}:submit-category-edit`,
}}
title="Edit category name"
instruction={this.instruction(newCategoryText)}
cancelTooltipContent="Close this dialog without editing this category."
primaryButtonText="Edit category name"
text={newCategoryText}
validationError={this.editedCategoryNameError(newCategoryText)}
handleSubmit={this.handleEditCategory}
handleCancel={this.disableEditCategoryMode}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ label: any; labelSuggestions: null; onChan... Remove this comment to see the full error message
label={newCategoryText}
labelSuggestions={null}
onChange={this.handleChangeOrSelect}
onSelect={this.handleChangeOrSelect}
inputProps={{
"data-testid": `${metadataField}:edit-category-name-text`,
leftIcon: "tag",
intent: "none",
autoFocus: true,
}}
newLabelMessage="New category"
/>
}
/>
</>
);
}
}
export default AnnoDialogEditCategoryName;
@@ -16,25 +16,16 @@ import { IconNames } from "@blueprintjs/icons";
import * as globals from "../../../globals";
import actions from "../../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
annotations: state.annotations,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class AnnoMenuCategory extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class AnnoMenuCategory extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
activateAddNewLabelMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch({
type: "annotation: activate add new label mode",
@@ -42,39 +33,30 @@ class AnnoMenuCategory extends React.PureComponent<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
activateEditCategoryMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch({
type: "annotation: activate category edit mode",
data: metadataField,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeleteCategory = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch(actions.annotationDeleteCategoryAction(metadataField));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message
annotations,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message
isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'createText' does not exist on type 'Read... Remove this comment to see the full error message
createText,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'editText' does not exist on type 'Readon... Remove this comment to see the full error message
editText,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'deleteText' does not exist on type 'Read... Remove this comment to see the full error message
deleteText,
} = this.props;
return (
<>
{isUserAnno ? (
@@ -0,0 +1,617 @@
import React, { useRef, useEffect } from "react";
import { connect, shallowEqual } from "react-redux";
import { FaChevronRight, FaChevronDown } from "react-icons/fa";
import {
AnchorButton,
Button,
Classes,
Position,
Tooltip,
} from "@blueprintjs/core";
import { Flipper, Flipped } from "react-flip-toolkit";
import Async from "react-async";
import memoize from "memoize-one";
import Value from "../value";
import AnnoMenu from "./annoMenuCategory";
import AnnoDialogEditCategoryName from "./annoDialogEditCategoryName";
import AnnoDialogAddLabel from "./annoDialogAddLabel";
import Truncate from "../../util/truncate";
import { CategoryCrossfilterContext } from "../categoryContext";
import * as globals from "../../../globals";
import { createCategorySummaryFromDfCol } from "../../../util/stateManager/controlsHelpers";
import {
createColorTable,
createColorQuery,
} from "../../../util/stateManager/colorHelpers";
import actions from "../../../actions";
const LABEL_WIDTH = globals.leftSidebarWidth - 100;
const ANNO_BUTTON_WIDTH = 50;
const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH;
@connect((state, ownProps) => {
const schema = state.annoMatrix?.schema;
const { metadataField } = ownProps;
const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable;
const categoricalSelection = state.categoricalSelection?.[metadataField];
return {
colors: state.colors,
categoricalSelection,
annotations: state.annotations,
annoMatrix: state.annoMatrix,
schema,
crossfilter: state.obsCrossfilter,
isUserAnno,
genesets: state.genesets.genesets,
};
})
class Category extends React.PureComponent {
static getSelectionState(
categoricalSelection,
metadataField,
categorySummary
) {
// total number of categories in this dimension
const totalCatCount = categorySummary.numCategoryValues;
// number of selected options in this category
const selectedCatCount = categorySummary.categoryValues.reduce(
(res, label) => (categoricalSelection.get(label) ?? true ? res + 1 : res),
0
);
return selectedCatCount === totalCatCount
? "all"
: selectedCatCount === 0
? "none"
: "some";
}
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol);
getSelectionState(categorySummary) {
const { categoricalSelection, metadataField } = this.props;
return Category.getSelectionState(
categoricalSelection,
metadataField,
categorySummary
);
}
handleColorChange = () => {
const { dispatch, metadataField } = this.props;
dispatch({
type: "color by categorical metadata",
colorAccessor: metadataField,
});
};
handleCategoryClick = () => {
const { annotations, metadataField, onExpansionChange } = this.props;
const editingCategory =
annotations.isEditingCategoryName &&
annotations.categoryBeingEdited === metadataField;
if (!editingCategory) {
onExpansionChange(metadataField);
}
};
handleCategoryKeyPress = (e) => {
if (e.key === "Enter") {
this.handleCategoryClick();
}
};
handleToggleAllClick = (categorySummary) => {
const isChecked = this.getSelectionState(categorySummary);
if (isChecked === "all") {
this.toggleNone(categorySummary);
} else {
this.toggleAll(categorySummary);
}
};
fetchAsyncProps = async (props) => {
const { annoMatrix, metadataField, colors } = props.watchProps;
const { crossfilter } = this.props;
const [categoryData, categorySummary, colorData] = await this.fetchData(
annoMatrix,
metadataField,
colors
);
return {
categoryData,
categorySummary,
colorData,
crossfilter,
...this.updateColorTable(colorData),
handleCategoryToggleAllClick: () =>
this.handleToggleAllClick(categorySummary),
};
};
async fetchData(annoMatrix, metadataField, colors) {
/*
fetch our data and the color-by data if appropriate, and then build a summary
of our category and a color table for the color-by annotation.
*/
const { schema } = annoMatrix;
const { colorAccessor, colorMode } = colors;
const { genesets } = this.props;
let colorDataPromise = Promise.resolve(null);
if (colorAccessor) {
const query = createColorQuery(
colorMode,
colorAccessor,
schema,
genesets
);
if (query) colorDataPromise = annoMatrix.fetch(...query);
}
const [categoryData, colorData] = await Promise.all([
annoMatrix.fetch("obs", metadataField),
colorDataPromise,
]);
// our data
const column = categoryData.icol(0);
const colSchema = schema.annotations.obsByName[metadataField];
const categorySummary = this.createCategorySummaryFromDfCol(
column,
colSchema
);
return [categoryData, categorySummary, colorData];
}
updateColorTable(colorData) {
// color table, which may be null
const { schema, colors, metadataField } = this.props;
const { colorAccessor, userColors, colorMode } = colors;
return {
isColorAccessor: colorAccessor === metadataField,
colorAccessor,
colorMode,
colorTable: createColorTable(
colorMode,
colorAccessor,
colorData,
schema,
userColors
),
};
}
toggleNone(categorySummary) {
const { dispatch, metadataField } = this.props;
dispatch(
actions.selectCategoricalAllMetadataAction(
"categorical metadata filter none of these",
metadataField,
categorySummary.allCategoryValues,
false
)
);
}
toggleAll(categorySummary) {
const { dispatch, metadataField } = this.props;
dispatch(
actions.selectCategoricalAllMetadataAction(
"categorical metadata filter all of these",
metadataField,
categorySummary.allCategoryValues,
true
)
);
}
render() {
const {
metadataField,
isExpanded,
categoricalSelection,
crossfilter,
colors,
annoMatrix,
isUserAnno,
} = this.props;
const checkboxID = `category-select-${metadataField}`;
return (
<CategoryCrossfilterContext.Provider value={crossfilter}>
<Async
watchFn={Category.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
metadataField,
annoMatrix,
categoricalSelection,
colors,
}}
>
<Async.Pending initial>
<StillLoading
metadataField={metadataField}
checkboxID={checkboxID}
/>
</Async.Pending>
<Async.Rejected>
{(error) => (
<ErrorLoading metadataField={metadataField} error={error} />
)}
</Async.Rejected>
<Async.Fulfilled persist>
{(asyncProps) => {
const {
colorAccessor,
colorTable,
colorData,
categoryData,
categorySummary,
isColorAccessor,
handleCategoryToggleAllClick,
} = asyncProps;
const selectionState = this.getSelectionState(categorySummary);
return (
<CategoryRender
metadataField={metadataField}
checkboxID={checkboxID}
isUserAnno={isUserAnno}
isExpanded={isExpanded}
isColorAccessor={isColorAccessor}
selectionState={selectionState}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
onColorChangeClick={this.handleColorChange}
onCategoryToggleAllClick={handleCategoryToggleAllClick}
onCategoryMenuClick={this.handleCategoryClick}
onCategoryMenuKeyPress={this.handleCategoryKeyPress}
/>
);
}}
</Async.Fulfilled>
</Async>
</CategoryCrossfilterContext.Provider>
);
}
}
export default Category;
const StillLoading = ({ metadataField, checkboxID }) =>
/*
We are still loading this category, so render a "busy" signal.
*/
(
<div
style={{
maxWidth: globals.maxControlsWidth,
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<div
style={{
display: "flex",
justifyContent: "flex-start",
alignItems: "flex-start",
}}
>
<label
htmlFor={checkboxID}
className={`${Classes.CONTROL} ${Classes.CHECKBOX}`}
>
<input disabled id={checkboxID} checked type="checkbox" />
<span className={Classes.CONTROL_INDICATOR} />
</label>
<Truncate>
<span
style={{
cursor: "pointer",
display: "inline-block",
width: LABEL_WIDTH,
}}
>
{metadataField}
</span>
</Truncate>
</div>
<div>
<Button minimal loading intent="primary" />
</div>
</div>
</div>
)
;
const ErrorLoading = ({ metadataField, error }) => {
console.error(error); // log error to console as it is unexpected.
return (
<div style={{ marginBottom: 10, marginTop: 4 }}>
<span
style={{
cursor: "pointer",
display: "inline-block",
width: LABEL_WIDTH,
fontStyle: "italic",
}}
>
{`Failure loading ${metadataField}`}
</span>
</div>
);
};
const CategoryHeader = React.memo(
({
metadataField,
checkboxID,
isUserAnno,
isColorAccessor,
isExpanded,
selectionState,
onColorChangeClick,
onCategoryMenuClick,
onCategoryMenuKeyPress,
onCategoryToggleAllClick,
}) => {
/*
Render category name and controls (eg, color-by button).
*/
const checkboxRef = useRef(null);
useEffect(() => {
checkboxRef.current.indeterminate = selectionState === "some";
}, [checkboxRef.current, selectionState]);
return (
<>
<div
style={{
display: "flex",
justifyContent: "flex-start",
alignItems: "flex-start",
}}
>
<label
className={`${Classes.CONTROL} ${Classes.CHECKBOX}`}
htmlFor={checkboxID}
>
<input
id={checkboxID}
data-testclass="category-select"
data-testid={`${metadataField}:category-select`}
onChange={onCategoryToggleAllClick}
ref={checkboxRef}
checked={selectionState === "all"}
type="checkbox"
/>
<span className={Classes.CONTROL_INDICATOR} />
</label>
<span
role="menuitem"
tabIndex="0"
data-testclass="category-expand"
data-testid={`${metadataField}:category-expand`}
onKeyPress={onCategoryMenuKeyPress}
style={{
cursor: "pointer",
}}
onClick={onCategoryMenuClick}
>
<Truncate>
<span
style={{
maxWidth: isUserAnno ? LABEL_WIDTH_ANNO : LABEL_WIDTH,
}}
data-testid={`${metadataField}:category-label`}
tabIndex="-1"
>
{metadataField}
</span>
</Truncate>
{isExpanded ? (
<FaChevronDown
data-testclass="category-expand-is-expanded"
style={{ fontSize: 10, marginLeft: 5 }}
/>
) : (
<FaChevronRight
data-testclass="category-expand-is-not-expanded"
style={{ fontSize: 10, marginLeft: 5 }}
/>
)}
</span>
</div>
{<AnnoDialogEditCategoryName metadataField={metadataField} />}
{<AnnoDialogAddLabel metadataField={metadataField} />}
<div>
<AnnoMenu
metadataField={metadataField}
isUserAnno={isUserAnno}
createText="Add a new label to this category"
editText="Edit this category's name"
deleteText="Delete this category, all associated labels, and remove all cell assignments"
/>
<Tooltip
content="Use as color scale"
position={Position.LEFT}
usePortal
hoverOpenDelay={globals.tooltipHoverOpenDelay}
modifiers={{
preventOverflow: { enabled: false },
hide: { enabled: false },
}}
>
<AnchorButton
data-testclass="colorby"
data-testid={`colorby-${metadataField}`}
onClick={onColorChangeClick}
active={isColorAccessor}
intent={isColorAccessor ? "primary" : "none"}
icon="tint"
/>
</Tooltip>
</div>
</>
);
}
);
const CategoryRender = React.memo(
({
metadataField,
checkboxID,
isUserAnno,
isColorAccessor,
isExpanded,
selectionState,
categoryData,
categorySummary,
colorAccessor,
colorData,
colorTable,
onColorChangeClick,
onCategoryMenuClick,
onCategoryMenuKeyPress,
onCategoryToggleAllClick,
}) => {
/*
Render the core of the category, including checkboxes, controls, etc.
*/
const { numCategoryValues } = categorySummary;
const isSingularValue = !isUserAnno && numCategoryValues === 1;
if (isSingularValue) {
/*
Entire category has a single value, special case.
*/
return null;
}
/*
Otherwise, our normal multi-layout layout
*/
return (
<div
style={{
maxWidth: globals.maxControlsWidth,
}}
data-testclass="category"
data-testid={`category-${metadataField}`}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<CategoryHeader
metadataField={metadataField}
checkboxID={checkboxID}
isUserAnno={isUserAnno}
isExpanded={isExpanded}
isColorAccessor={isColorAccessor}
selectionState={selectionState}
onColorChangeClick={onColorChangeClick}
onCategoryToggleAllClick={onCategoryToggleAllClick}
onCategoryMenuClick={onCategoryMenuClick}
onCategoryMenuKeyPress={onCategoryMenuKeyPress}
/>
</div>
<div style={{ marginLeft: 26 }}>
{
/* values*/
isExpanded ? (
<CategoryValueList
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
) : null
}
</div>
</div>
);
}
);
const CategoryValueList = React.memo(
({
isUserAnno,
metadataField,
categoryData,
categorySummary,
colorAccessor,
colorData,
colorTable,
}) => {
const tuples = [...categorySummary.categoryValueIndices];
/*
Render the value list. If this is a user annotation, we use a flipper
animation, if read-only, we don't bother and save a few bits of perf.
*/
if (!isUserAnno) {
return (
<>
{tuples.map(([value, index]) => (
<Value
key={value}
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryIndex={index}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
))}
</>
);
}
/* User annotation */
const flipKey = tuples.map((t) => t[0]).join("");
return (
<Flipper flipKey={flipKey}>
{tuples.map(([value, index]) => (
<Flipped key={value} flipId={value}>
<Value
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryIndex={index}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
</Flipped>
))}
</Flipper>
);
}
);
@@ -1,724 +0,0 @@
import React, { useRef, useEffect } from "react";
import { connect, shallowEqual } from "react-redux";
import { FaChevronRight, FaChevronDown } from "react-icons/fa";
import {
AnchorButton,
Button,
Classes,
Position,
Tooltip,
} from "@blueprintjs/core";
import { Flipper, Flipped } from "react-flip-toolkit";
import Async from "react-async";
import memoize from "memoize-one";
import Value from "../value";
import AnnoMenu from "./annoMenuCategory";
import AnnoDialogEditCategoryName from "./annoDialogEditCategoryName";
import AnnoDialogAddLabel from "./annoDialogAddLabel";
import Truncate from "../../util/truncate";
import { CategoryCrossfilterContext } from "../categoryContext";
import * as globals from "../../../globals";
import { createCategorySummaryFromDfCol } from "../../../util/stateManager/controlsHelpers";
import {
createColorTable,
createColorQuery,
} from "../../../util/stateManager/colorHelpers";
import actions from "../../../actions";
import { Dataframe } from "../../../util/dataframe";
const LABEL_WIDTH = globals.leftSidebarWidth - 100;
const ANNO_BUTTON_WIDTH = 50;
const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state, ownProps) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const schema = (state as any).annoMatrix?.schema;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
const { metadataField } = ownProps;
const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const categoricalSelection = (state as any).categoricalSelection?.[
metadataField
];
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
categoricalSelection,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
crossfilter: (state as any).obsCrossfilter,
isUserAnno,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
};
})
class Category extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
static getSelectionState(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
categoricalSelection: any,
// @ts-expect-error ts-migrate(6133) FIXME: 'metadataField' is declared but its value is never... Remove this comment to see the full error message
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
metadataField: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
categorySummary: any
) {
// total number of categories in this dimension
const totalCatCount = categorySummary.numCategoryValues;
// number of selected options in this category
const selectedCatCount = categorySummary.categoryValues.reduce(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(res: any, label: any) =>
categoricalSelection.get(label) ?? true ? res + 1 : res,
0
);
return selectedCatCount === totalCatCount
? "all"
: selectedCatCount === 0
? "none"
: "some";
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
getSelectionState(categorySummary: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
const { categoricalSelection, metadataField } = this.props;
return Category.getSelectionState(
categoricalSelection,
metadataField,
categorySummary
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleColorChange = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch({
type: "color by categorical metadata",
colorAccessor: metadataField,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleCategoryClick = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message
const { annotations, metadataField, onExpansionChange } = this.props;
const editingCategory =
annotations.isEditingCategoryName &&
annotations.categoryBeingEdited === metadataField;
if (!editingCategory) {
onExpansionChange(metadataField);
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCategoryKeyPress = (e: any) => {
if (e.key === "Enter") {
this.handleCategoryClick();
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleToggleAllClick = (categorySummary: any) => {
const isChecked = this.getSelectionState(categorySummary);
if (isChecked === "all") {
this.toggleNone(categorySummary);
} else {
this.toggleAll(categorySummary);
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
const { annoMatrix, metadataField, colors } = props.watchProps;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message
const { crossfilter } = this.props;
const [categoryData, categorySummary, colorData] = await this.fetchData(
annoMatrix,
metadataField,
colors
);
return {
categoryData,
categorySummary,
colorData,
crossfilter,
...this.updateColorTable(colorData),
handleCategoryToggleAllClick: () =>
this.handleToggleAllClick(categorySummary),
};
};
async fetchData(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
annoMatrix: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
metadataField: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colors: any
): Promise<
[
Dataframe,
ReturnType<typeof createCategorySummaryFromDfCol>,
Dataframe | null
]
> {
/*
fetch our data and the color-by data if appropriate, and then build a summary
of our category and a color table for the color-by annotation.
*/
const { schema } = annoMatrix;
const { colorAccessor, colorMode } = colors;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
const { genesets } = this.props;
let colorDataPromise: Promise<Dataframe | null> = Promise.resolve(null);
if (colorAccessor) {
const query = createColorQuery(
colorMode,
colorAccessor,
schema,
genesets
);
if (query) colorDataPromise = annoMatrix.fetch(...query);
}
const [categoryData, colorData] = await Promise.all<
Dataframe,
Dataframe | null
>([annoMatrix.fetch("obs", metadataField), colorDataPromise]);
// our data
const column = categoryData.icol(0);
const colSchema = schema.annotations.obsByName[metadataField];
const categorySummary = this.createCategorySummaryFromDfCol(
column,
colSchema
);
return [categoryData, categorySummary, colorData];
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -- - FIXME: disabled temporarily on migrate to TS.
updateColorTable(colorData: Dataframe|null) {
// color table, which may be null
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
const { schema, colors, metadataField } = this.props;
const { colorAccessor, userColors, colorMode } = colors;
return {
isColorAccessor: colorAccessor === metadataField,
colorAccessor,
colorMode,
colorTable: createColorTable(
colorMode,
colorAccessor,
colorData,
schema,
userColors
),
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
toggleNone(categorySummary: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch(
actions.selectCategoricalAllMetadataAction(
"categorical metadata filter none of these",
metadataField,
categorySummary.allCategoryValues,
false
)
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
toggleAll(categorySummary: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField } = this.props;
dispatch(
actions.selectCategoricalAllMetadataAction(
"categorical metadata filter all of these",
metadataField,
categorySummary.allCategoryValues,
true
)
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type 'Read... Remove this comment to see the full error message
isExpanded,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
categoricalSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message
crossfilter,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message
isUserAnno,
} = this.props;
const checkboxID = `category-select-${metadataField}`;
return (
<CategoryCrossfilterContext.Provider value={crossfilter}>
<Async
watchFn={Category.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
metadataField,
annoMatrix,
categoricalSelection,
colors,
}}
>
<Async.Pending initial>
<StillLoading
metadataField={metadataField}
checkboxID={checkboxID}
/>
</Async.Pending>
<Async.Rejected>
{(error) => (
<ErrorLoading metadataField={metadataField} error={error} />
)}
</Async.Rejected>
<Async.Fulfilled persist>
{(asyncProps) => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'u... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'unkn... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'unkno... Remove this comment to see the full error message
colorData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'un... Remove this comment to see the full error message
categoryData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCategoryToggleAllClick' does not e... Remove this comment to see the full error message
handleCategoryToggleAllClick,
} = asyncProps;
const selectionState = this.getSelectionState(categorySummary);
return (
<CategoryRender
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; checkboxID: string; is... Remove this comment to see the full error message
metadataField={metadataField}
checkboxID={checkboxID}
isUserAnno={isUserAnno}
isExpanded={isExpanded}
isColorAccessor={isColorAccessor}
selectionState={selectionState}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
onColorChangeClick={this.handleColorChange}
onCategoryToggleAllClick={handleCategoryToggleAllClick}
onCategoryMenuClick={this.handleCategoryClick}
onCategoryMenuKeyPress={this.handleCategoryKeyPress}
/>
);
}}
</Async.Fulfilled>
</Async>
</CategoryCrossfilterContext.Provider>
);
}
}
export default Category;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const StillLoading = ({ metadataField, checkboxID }: any) => (
/*
We are still loading this category, so render a "busy" signal.
*/
<div
style={{
maxWidth: globals.maxControlsWidth,
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<div
style={{
display: "flex",
justifyContent: "flex-start",
alignItems: "flex-start",
}}
>
<label
htmlFor={checkboxID}
className={`${Classes.CONTROL} ${Classes.CHECKBOX}`}
>
<input disabled id={checkboxID} checked type="checkbox" />
<span className={Classes.CONTROL_INDICATOR} />
</label>
<Truncate>
<span
style={{
cursor: "pointer",
display: "inline-block",
width: LABEL_WIDTH,
}}
>
{metadataField}
</span>
</Truncate>
</div>
<div>
<Button minimal loading intent="primary" />
</div>
</div>
</div>
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const ErrorLoading = ({ metadataField, error }: any) => {
console.error(error); // log error to console as it is unexpected.
return (
<div style={{ marginBottom: 10, marginTop: 4 }}>
<span
style={{
cursor: "pointer",
display: "inline-block",
width: LABEL_WIDTH,
fontStyle: "italic",
}}
>
{`Failure loading ${metadataField}`}
</span>
</div>
);
};
const CategoryHeader = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'checkboxID' does not exist on type '{ ch... Remove this comment to see the full error message
checkboxID,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message
isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type '{ ch... Remove this comment to see the full error message
isExpanded,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionState' does not exist on type '... Remove this comment to see the full error message
selectionState,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onColorChangeClick' does not exist on ty... Remove this comment to see the full error message
onColorChangeClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuClick' does not exist on t... Remove this comment to see the full error message
onCategoryMenuClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message
onCategoryMenuKeyPress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message
onCategoryToggleAllClick,
}) => {
/*
Render category name and controls (eg, color-by button).
*/
const checkboxRef = useRef(null);
useEffect(() => {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
checkboxRef.current.indeterminate = selectionState === "some";
}, [checkboxRef.current, selectionState]);
return (
<>
<div
style={{
display: "flex",
justifyContent: "flex-start",
alignItems: "flex-start",
}}
>
<label
className={`${Classes.CONTROL} ${Classes.CHECKBOX}`}
htmlFor={checkboxID}
>
<input
id={checkboxID}
data-testclass="category-select"
data-testid={`${metadataField}:category-select`}
onChange={onCategoryToggleAllClick}
ref={checkboxRef}
checked={selectionState === "all"}
type="checkbox"
/>
<span className={Classes.CONTROL_INDICATOR} />
</label>
<span
role="menuitem"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="0"
data-testclass="category-expand"
data-testid={`${metadataField}:category-expand`}
onKeyPress={onCategoryMenuKeyPress}
style={{
cursor: "pointer",
}}
onClick={onCategoryMenuClick}
>
<Truncate>
<span
style={{
maxWidth: isUserAnno ? LABEL_WIDTH_ANNO : LABEL_WIDTH,
}}
data-testid={`${metadataField}:category-label`}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="-1"
>
{metadataField}
</span>
</Truncate>
{isExpanded ? (
<FaChevronDown
data-testclass="category-expand-is-expanded"
style={{ fontSize: 10, marginLeft: 5 }}
/>
) : (
<FaChevronRight
data-testclass="category-expand-is-not-expanded"
style={{ fontSize: 10, marginLeft: 5 }}
/>
)}
</span>
</div>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; }' is not assignable t... Remove this comment to see the full error message */}
<AnnoDialogEditCategoryName metadataField={metadataField} />
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; }' is not assignable t... Remove this comment to see the full error message */}
<AnnoDialogAddLabel metadataField={metadataField} />
<div>
<AnnoMenu
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; isUserAnno: any; creat... Remove this comment to see the full error message
metadataField={metadataField}
isUserAnno={isUserAnno}
createText="Add a new label to this category"
editText="Edit this category's name"
deleteText="Delete this category, all associated labels, and remove all cell assignments"
/>
<Tooltip
content="Use as color scale"
position={Position.LEFT}
usePortal
hoverOpenDelay={globals.tooltipHoverOpenDelay}
modifiers={{
preventOverflow: { enabled: false },
hide: { enabled: false },
}}
>
<AnchorButton
data-testclass="colorby"
data-testid={`colorby-${metadataField}`}
onClick={onColorChangeClick}
active={isColorAccessor}
intent={isColorAccessor ? "primary" : "none"}
icon="tint"
/>
</Tooltip>
</div>
</>
);
}
);
const CategoryRender = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'checkboxID' does not exist on type '{ ch... Remove this comment to see the full error message
checkboxID,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message
isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type '{ ch... Remove this comment to see the full error message
isExpanded,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionState' does not exist on type '... Remove this comment to see the full error message
selectionState,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type '{ ... Remove this comment to see the full error message
categoryData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type '{... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type '{ chi... Remove this comment to see the full error message
colorData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type '{ ch... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onColorChangeClick' does not exist on ty... Remove this comment to see the full error message
onColorChangeClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuClick' does not exist on t... Remove this comment to see the full error message
onCategoryMenuClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message
onCategoryMenuKeyPress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message
onCategoryToggleAllClick,
}) => {
/*
Render the core of the category, including checkboxes, controls, etc.
*/
const { numCategoryValues } = categorySummary;
const isSingularValue = !isUserAnno && numCategoryValues === 1;
if (isSingularValue) {
/*
Entire category has a single value, special case.
*/
return null;
}
/*
Otherwise, our normal multi-layout layout
*/
return (
<div
style={{
maxWidth: globals.maxControlsWidth,
}}
data-testclass="category"
data-testid={`category-${metadataField}`}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<CategoryHeader
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; checkboxID: any; isUse... Remove this comment to see the full error message
metadataField={metadataField}
checkboxID={checkboxID}
isUserAnno={isUserAnno}
isExpanded={isExpanded}
isColorAccessor={isColorAccessor}
selectionState={selectionState}
onColorChangeClick={onColorChangeClick}
onCategoryToggleAllClick={onCategoryToggleAllClick}
onCategoryMenuClick={onCategoryMenuClick}
onCategoryMenuKeyPress={onCategoryMenuKeyPress}
/>
</div>
<div style={{ marginLeft: 26 }}>
{
/* values*/
isExpanded ? (
<CategoryValueList
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isUserAnno: any; metadataField: any; categ... Remove this comment to see the full error message
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
) : null
}
</div>
</div>
);
}
);
const CategoryValueList = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message
isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type '{ ... Remove this comment to see the full error message
categoryData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type '{... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type '{ chi... Remove this comment to see the full error message
colorData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type '{ ch... Remove this comment to see the full error message
colorTable,
}) => {
const tuples = [...categorySummary.categoryValueIndices];
/*
Render the value list. If this is a user annotation, we use a flipper
animation, if read-only, we don't bother and save a few bits of perf.
*/
if (!isUserAnno) {
return (
<>
{tuples.map(([value, index]) => (
<Value
key={value}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: any; isUserAnno: any; metadataField: ... Remove this comment to see the full error message
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryIndex={index}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
))}
</>
);
}
/* User annotation */
const flipKey = tuples.map((t) => t[0]).join("");
return (
<Flipper flipKey={flipKey}>
{tuples.map(([value, index]) => (
<Flipped key={value} flipId={value}>
<Value
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isUserAnno: any; metadataField: any; categ... Remove this comment to see the full error message
isUserAnno={isUserAnno}
metadataField={metadataField}
categoryIndex={index}
categoryData={categoryData}
categorySummary={categorySummary}
colorAccessor={colorAccessor}
colorData={colorData}
colorTable={colorTable}
/>
</Flipped>
))}
</Flipper>
);
}
);
@@ -10,23 +10,13 @@ import LabelInput from "../labelInput";
import { labelPrompt } from "./labelUtil";
import actions from "../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
writableCategoriesEnabled:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.annotations ?? false,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userInfo: (state as any).userInfo,
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false,
schema: state.annoMatrix?.schema,
userInfo: state.userInfo,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Categories extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class Categories extends React.Component {
constructor(props) {
super(props);
this.state = {
createAnnoModeActive: false,
@@ -36,9 +26,7 @@ class Categories extends React.Component<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCreateUserAnno = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleCreateUserAnno = (e) => {
const { dispatch } = this.props;
const { newCategoryText, categoryToDuplicate } = this.state;
dispatch(
@@ -55,12 +43,10 @@ class Categories extends React.Component<{}, State> {
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleEnableAnnoMode = () => {
this.setState({ createAnnoModeActive: true });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDisableAnnoMode = () => {
this.setState({
createAnnoModeActive: false,
@@ -69,58 +55,56 @@ class Categories extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleModalDuplicateCategorySelection = (d: any) => {
handleModalDuplicateCategorySelection = (d) => {
this.setState({ categoryToDuplicate: d });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
categoryNameError = (name: any) => {
categoryNameError = (name) => {
/*
return false if this is a LEGAL/acceptable category name or NULL/empty string,
or return an error type.
*/
return false if this is a LEGAL/acceptable category name or NULL/empty string,
or return an error type.
*/
/* allow empty string */
if (name === "") return false;
/*
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
test for uniqueness against *all* annotation names, not just the subset
we render as categorical.
*/
const { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(c: any) => c.name
);
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name);
/* check category name syntax */
const error = AnnotationsHelpers.annotationNameIsErroneous(name);
if (error) {
return error;
}
/* disallow duplicates */
if (allCategoryNames.indexOf(name) !== -1) {
return "duplicate";
}
/* otherwise, no error */
return false;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChange = (name: any) => {
handleChange = (name) => {
this.setState({ newCategoryText: name });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleSelect = (name: any) => {
handleSelect = (name) => {
this.setState({ newCategoryText: name });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
instruction = (name: any) =>
labelPrompt(this.categoryNameError(name), "New, unique category name", ":");
instruction = (name) => labelPrompt(
this.categoryNameError(name),
"New, unique category name",
":"
);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
onExpansionChange = (catName: any) => {
onExpansionChange = (catName) => {
const { expandedCats } = this.state;
if (expandedCats.has(catName)) {
const _expandedCats = new Set(expandedCats);
@@ -133,7 +117,6 @@ class Categories extends React.Component<{}, State> {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
createAnnoModeActive,
@@ -141,13 +124,11 @@ class Categories extends React.Component<{}, State> {
newCategoryText,
expandedCats,
} = this.state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
const { writableCategoriesEnabled, schema, userInfo } = this.props;
/* all names, sorted in display order. Will be rendered in this order */
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const allCategoryNames = ControlsHelpers.selectableCategoryNames(
schema
).sort();
const allCategoryNames =
ControlsHelpers.selectableCategoryNames(schema).sort();
return (
<div
style={{
@@ -155,7 +136,6 @@ class Categories extends React.Component<{}, State> {
}}
>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; title: string; instruction:... Remove this comment to see the full error message
isActive={createAnnoModeActive}
title="Create new category"
instruction={this.instruction(newCategoryText)}
@@ -168,7 +148,6 @@ class Categories extends React.Component<{}, State> {
handleCancel={this.handleDisableAnnoMode}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ labelSuggestions: null; onChange: (name: a... Remove this comment to see the full error message
labelSuggestions={null}
onChange={this.handleChange}
onSelect={this.handleSelect}
@@ -183,7 +162,6 @@ class Categories extends React.Component<{}, State> {
}
annoSelect={
<AnnoSelect
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ handleModalDuplicateCategorySelection: (d:... Remove this comment to see the full error message
handleModalDuplicateCategorySelection={
this.handleModalDuplicateCategorySelection
}
@@ -192,6 +170,7 @@ class Categories extends React.Component<{}, State> {
/>
}
/>
{writableCategoriesEnabled ? (
<div style={{ marginBottom: 10 }}>
<Tooltip
@@ -220,16 +199,15 @@ class Categories extends React.Component<{}, State> {
</Tooltip>
</div>
) : null}
{/* READ ONLY CATEGORICAL FIELDS */}
{/* this is duplicative but flat, could be abstracted */}
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS */}
{allCategoryNames.map((catName: any) =>
{allCategoryNames.map((catName) =>
!schema.annotations.obsByName[catName].writable &&
(schema.annotations.obsByName[catName].categories?.length > 1 ||
!schema.annotations.obsByName[catName].categories) ? (
<Category
key={catName}
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
metadataField={catName}
onExpansionChange={this.onExpansionChange}
isExpanded={expandedCats.has(catName)}
@@ -238,12 +216,10 @@ class Categories extends React.Component<{}, State> {
) : null
)}
{/* WRITEABLE FIELDS */}
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS */}
{allCategoryNames.map((catName: any) =>
{allCategoryNames.map((catName) =>
schema.annotations.obsByName[catName].writable ? (
<Category
key={catName}
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
metadataField={catName}
onExpansionChange={this.onExpansionChange}
isExpanded={expandedCats.has(catName)}
@@ -3,8 +3,7 @@ import { Colors } from "@blueprintjs/core";
import { AnnotationsHelpers } from "../../util/stateManager";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function isLabelErroneous(label: any, metadataField: any, schema: any) {
export function isLabelErroneous(label, metadataField, schema) {
/*
return false if this is a LEGAL/acceptable category name or NULL/empty string,
or return an error type.
@@ -36,11 +35,9 @@ const errorMessageMap = {
"multi-space-run": "Multiple consecutive spaces not allowed",
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function labelPrompt(err: any, prolog: any, epilog: any) {
export function labelPrompt(err, prolog, epilog) {
let errPrompt = null;
if (err) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
let errMsg = errorMessageMap[err] ?? "error";
errMsg = errMsg[0].toLowerCase() + errMsg.slice(1);
errPrompt = (
@@ -13,7 +13,6 @@ import {
Position,
} from "@blueprintjs/core";
import * as globals from "../../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module '../categorical.css' or its cor... Remove this comment to see the full error message
import styles from "../categorical.css";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
@@ -25,28 +24,20 @@ import actions from "../../../actions";
import MiniHistogram from "../../miniHistogram";
import MiniStackedBar from "../../miniStackedBar";
import { CategoryCrossfilterContext } from "../categoryContext";
import { Dataframe, ContinuousHistogram } from "../../../util/dataframe";
const STACKED_BAR_HEIGHT = 11;
const STACKED_BAR_WIDTH = 100;
/* this is defined outside of the class so we can use it in connect() */
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function _currentLabelAsString(ownProps: any) {
function _currentLabelAsString(ownProps) {
const { label } = ownProps;
// when called as a function, the String() constructor performs type conversion,
// and returns a primitive string.
return String(label);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state, ownProps) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on type 'D... Remove this comment to see the full error message
const { pointDilation, categoricalSelection } = state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message
const { metadataField, categorySummary, categoryIndex } = ownProps;
const isDilated =
pointDilation.metadataField === metadataField &&
@@ -57,35 +48,27 @@ type State = any;
const isSelected = category.get(label) ?? true;
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
annotations: state.annotations,
schema: state.annoMatrix?.schema,
isDilated,
isSelected,
label,
};
})
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class CategoryValue extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class CategoryValue extends React.Component {
constructor(props) {
super(props);
this.state = {
editedLabelText: this.currentLabelAsString(),
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
componentDidUpdate(prevProps: {}) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
componentDidUpdate(prevProps) {
const { metadataField, categoryIndex, categorySummary } = this.props;
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(prevProps as any).metadataField !== metadataField ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(prevProps as any).categoryIndex !== categoryIndex || // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(prevProps as any).categorySummary !== categorySummary
prevProps.metadataField !== metadataField ||
prevProps.categoryIndex !== categoryIndex ||
prevProps.categorySummary !== categorySummary
) {
// eslint-disable-next-line react/no-did-update-set-state --- adequately checked to prevent looping
this.setState({
@@ -95,31 +78,23 @@ class CategoryValue extends React.Component<{}, State> {
}
// If coloring by and this isn't the colorAccessor and it isn't being edited
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
get shouldRenderStackedBarOrHistogram() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
const { colorAccessor, isColorBy, annotations } = this.props;
return !!colorAccessor && !isColorBy && !annotations.isEditingLabelName;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeleteValue = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, label } = this.props;
dispatch(actions.annotationDeleteLabelFromCategory(metadataField, label));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleAddCurrentSelectionToThisLabel = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, label } = this.props;
dispatch(actions.annotationLabelCurrentSelection(metadataField, label));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleEditValue = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleEditValue = (e) => {
const { dispatch, metadataField, label } = this.props;
const { editedLabelText } = this.state;
this.cancelEditMode();
@@ -133,9 +108,7 @@ class CategoryValue extends React.Component<{}, State> {
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCreateArbitraryLabel = (txt: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleCreateArbitraryLabel = (txt) => {
const { dispatch, metadataField, label } = this.props;
this.cancelEditMode();
dispatch(
@@ -143,21 +116,15 @@ class CategoryValue extends React.Component<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
labelNameError = (name: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
labelNameError = (name) => {
const { metadataField, schema } = this.props;
if (name === this.currentLabelAsString()) return false;
return isLabelErroneous(name, metadataField, schema);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
instruction = (label: any) =>
labelPrompt(this.labelNameError(label), "New, unique label", ":");
instruction = (label) => labelPrompt(this.labelNameError(label), "New, unique label", ":");
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
activateEditLabelMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({
type: "annotation: activate edit label mode",
@@ -167,9 +134,7 @@ class CategoryValue extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
cancelEditMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, categoryIndex, label } = this.props;
this.setState({
editedLabelText: this.currentLabelAsString(),
@@ -182,18 +147,9 @@ class CategoryValue extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
toggleOff = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message
categoryIndex,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
} = this.props;
const { dispatch, metadataField, categoryIndex, categorySummary } =
this.props;
const label = categorySummary.categoryValues[categoryIndex];
dispatch(
actions.selectCategoricalMetadataAction(
@@ -206,8 +162,7 @@ class CategoryValue extends React.Component<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
shouldComponentUpdate = (nextProps: any, nextState: any) => {
shouldComponentUpdate = (nextProps, nextState) => {
/*
Checks to see if at least one of the following changed:
* world state
@@ -218,7 +173,6 @@ class CategoryValue extends React.Component<{}, State> {
If and only if true, update the component
*/
const { props, state } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message
const { categoryIndex, categorySummary, isSelected } = props;
const {
categoryIndex: newCategoryIndex,
@@ -231,15 +185,10 @@ class CategoryValue extends React.Component<{}, State> {
const labelChanged = label !== newLabel;
const valueSelectionChange = isSelected !== newIsSelected;
const colorAccessorChange =
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(props as any).colorAccessor !== nextProps.colorAccessor;
const annotationsChange =
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(props as any).annotations !== nextProps.annotations;
const colorAccessorChange = props.colorAccessor !== nextProps.colorAccessor;
const annotationsChange = props.annotations !== nextProps.annotations;
const editingLabel = state.editedLabelText !== nextState.editedLabelText;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const dilationChange = (props as any).isDilated !== nextProps.isDilated;
const dilationChange = props.isDilated !== nextProps.isDilated;
const count = categorySummary.categoryValueCounts[categoryIndex];
const newCount = newCategorySummary.categoryValueCounts[newCategoryIndex];
@@ -250,8 +199,7 @@ class CategoryValue extends React.Component<{}, State> {
// if any one changes, but only for the currently colored-by category.
const colorMightHaveChanged =
nextProps.colorAccessor === nextProps.metadataField &&
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(props as any).categorySummary !== nextProps.categorySummary;
props.categorySummary !== nextProps.categorySummary;
return (
labelChanged ||
@@ -265,18 +213,9 @@ class CategoryValue extends React.Component<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
toggleOn = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message
categoryIndex,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
} = this.props;
const { dispatch, metadataField, categoryIndex, categorySummary } =
this.props;
const label = categorySummary.categoryValues[categoryIndex];
dispatch(
actions.selectCategoricalMetadataAction(
@@ -289,9 +228,7 @@ class CategoryValue extends React.Component<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleMouseEnter = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({
type: "category value mouse hover start",
@@ -301,9 +238,7 @@ class CategoryValue extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleMouseExit = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({
type: "category value mouse hover end",
@@ -313,32 +248,23 @@ class CategoryValue extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleTextChange = (text: any) => {
handleTextChange = (text) => {
this.setState({ editedLabelText: text });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChoice = (e: any) => {
handleChoice = (e) => {
/* Blueprint Suggest format */
this.setState({ editedLabelText: e.target });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
createHistogramBins = (
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
metadataField: any,
categoryData: Dataframe,
// @ts-expect-error ts-migrate(6133) FIXME: 'colorAccessor' is declared but its value is never... Remove this comment to see the full error message
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorAccessor: any,
colorData: Dataframe,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
categoryValue: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
width: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
height: any
metadataField,
categoryData,
colorAccessor,
colorData,
categoryValue,
width,
height
) => {
/*
Knowing that colorScale is based off continuous data,
@@ -347,17 +273,17 @@ class CategoryValue extends React.Component<{}, State> {
*/
const groupBy = categoryData.col(metadataField);
const col = colorData.icol(0);
const range = col.summarizeContinuous();
const range = col.summarize();
const histogramMap = col.histogramContinuousBy(
const histogramMap = col.histogram(
50,
[range.min, range.max],
groupBy
);
); /* Because the signature changes we really need different names for histogram to differentiate signatures */
const bins = histogramMap.has(categoryValue)
? histogramMap.get(categoryValue) as ContinuousHistogram
: new Array<number>(50).fill(0);
? histogramMap.get(categoryValue)
: new Array(50).fill(0);
const xScale = d3.scaleLinear().domain([0, bins.length]).range([0, width]);
@@ -372,23 +298,15 @@ class CategoryValue extends React.Component<{}, State> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
createStackedGraphBins = (
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
metadataField: any,
categoryData: Dataframe,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorAccessor: any,
colorData: Dataframe,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
categoryValue: any,
// @ts-expect-error ts-migrate(6133) FIXME: 'colorTable' is declared but its value is never re... Remove this comment to see the full error message
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorTable: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
schema: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
width: any
metadataField,
categoryData,
colorAccessor,
colorData,
categoryValue,
colorTable,
schema,
width
) => {
/*
Knowing that the color scale is based off of categorical data,
@@ -398,7 +316,7 @@ class CategoryValue extends React.Component<{}, State> {
const groupBy = categoryData.col(metadataField);
const occupancyMap = colorData
.col(colorAccessor)
.histogramCategoricalBy(groupBy);
.histogramCategorical(groupBy);
const occupancy = occupancyMap.get(categoryValue);
@@ -425,19 +343,16 @@ class CategoryValue extends React.Component<{}, State> {
return null;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
currentLabelAsString() {
return _currentLabelAsString(this.props);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
isAddCurrentSelectionDisabled(crossfilter: any, category: any, value: any) {
isAddCurrentSelectionDisabled(crossfilter, category, value) {
/*
disable "add current selection to label", if one of the following is true:
1. no cells are selected
2. all currently selected cells already have this label, on this category
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message
const { categoryData } = this.props;
// 1. no cells selected?
@@ -455,22 +370,14 @@ class CategoryValue extends React.Component<{}, State> {
return false;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderMiniStackedBar = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message
categoryData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message
colorData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
schema,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message
label,
} = this.props;
const isColorBy = metadataField === colorAccessor;
@@ -508,29 +415,20 @@ class CategoryValue extends React.Component<{}, State> {
domain,
occupancy,
}}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ height: number; width: number; colorTable:... Remove this comment to see the full error message
height={STACKED_BAR_HEIGHT}
width={STACKED_BAR_WIDTH}
/>
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderMiniHistogram = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message
colorData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message
categoryData,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
schema,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message
label,
} = this.props;
const colorScale = colorTable?.scale;
@@ -565,7 +463,6 @@ class CategoryValue extends React.Component<{}, State> {
yScale,
bins,
}}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ obsOrVarContinuousFieldDisplayName: any; d... Remove this comment to see the full error message
obsOrVarContinuousFieldDisplayName={colorAccessor}
domainLabel={label}
height={STACKED_BAR_HEIGHT}
@@ -574,28 +471,17 @@ class CategoryValue extends React.Component<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message
categoryIndex,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message
isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message
annotations,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isDilated' does not exist on type 'Reado... Remove this comment to see the full error message
isDilated,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isSelected' does not exist on type 'Read... Remove this comment to see the full error message
isSelected,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message
categorySummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message
label,
} = this.props;
const colorScale = colorTable?.scale;
@@ -691,7 +577,6 @@ class CategoryValue extends React.Component<{}, State> {
<span
data-testid={`categorical-value-${metadataField}-${displayString}`}
data-testclass="categorical-value"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="-1"
style={{
width: labelWidth,
@@ -717,7 +602,6 @@ class CategoryValue extends React.Component<{}, State> {
{editModeActive ? (
<div>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; inputProps: { "data-testid"... Remove this comment to see the full error message
isActive={editModeActive}
inputProps={{
"data-testid": `${metadataField}:edit-label-name-dialog`,
@@ -736,7 +620,6 @@ class CategoryValue extends React.Component<{}, State> {
handleCancel={this.cancelEditMode}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ label: any; labelSuggestions: null; onChan... Remove this comment to see the full error message
label={editedLabelText}
labelSuggestions={null}
onChange={this.handleTextChange}
@@ -8,62 +8,60 @@ import {
Position,
} from "@blueprintjs/core";
import { Dataframe } from "../../../util/dataframe";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
schema: state.annoMatrix?.schema,
}))
class Occupancy extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
canvas: any;
_WIDTH = 100;
_HEIGHT = 11;
createHistogram = (): void => {
createHistogram = () => {
/*
Knowing that colorScale is based off continuous data,
createHistogram fetches the continuous data in relation to the cells relevant to the category value.
It then separates that data into 50 bins for drawing the mini-histogram
*/
const { metadataField, categoryData, colorData, categoryValue } = this
.props as {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
metadataField;
categoryData: Dataframe;
colorData: Dataframe;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryValue' does not exist on type 'R... Remove this comment to see the full error message
categoryValue;
};
Knowing that colorScale is based off continous data,
createHistogram fetches the continous data in relation to the cells releveant to the catagory value.
It then seperates that data into 50 bins for drawing the mini-histogram
*/
const { metadataField, categoryData, colorData, categoryValue } =
this.props;
if (!this.canvas) return;
const groupBy = categoryData.col(metadataField);
const col = colorData.icol(0);
const range = col.summarizeContinuous();
const histogramMap = col.histogramContinuousBy(
const range = col.summarize();
const histogramMap = col.histogram(
50,
[range.min, range.max],
groupBy
);
); /* Because the signature changes we really need different names for histogram to differentiate signatures */
const bins = histogramMap.has(categoryValue)
? (histogramMap.get(categoryValue) as number[])
? histogramMap.get(categoryValue)
: new Array(50).fill(0);
const xScale = d3
.scaleLinear()
.domain([0, bins.length])
.range([0, this._WIDTH]);
const largestBin = Math.max(...bins);
const yScale = d3
.scaleLinear()
.domain([0, largestBin])
.range([0, this._HEIGHT]);
const ctx = this.canvas.getContext("2d");
ctx.fillStyle = "#000";
let x;
let y;
const rectWidth = this._WIDTH / bins.length;
for (let i = 0, { length } = bins; i < length; i += 1) {
x = xScale(i);
y = yScale(bins[i]);
@@ -71,12 +69,12 @@ class Occupancy extends React.PureComponent {
}
};
createOccupancyStack = (): void => {
createOccupancyStack = () => {
/*
Knowing that the color scale is based off of catagorical data,
createOccupancyStack obtains a map showing the number if cells per colored value
Using the colorScale a stack of colored bars is drawn representing the map
*/
Knowing that the color scale is based off of catagorical data,
createOccupancyStack obtains a map showing the number if cells per colored value
Using the colorScale a stack of colored bars is drawn representing the map
*/
const {
metadataField,
categoryData,
@@ -85,28 +83,20 @@ class Occupancy extends React.PureComponent {
colorTable,
schema,
colorData,
} = this.props as {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
metadataField: any;
categoryData: Dataframe;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colorAccessor: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
categoryValue: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colorTable: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: any;
colorData: Dataframe;
};
} = this.props;
const { scale: colorScale } = colorTable;
const ctx = this.canvas?.getContext("2d");
if (!ctx) return;
const groupBy = categoryData.col(metadataField);
const occupancyMap = colorData
.col(colorAccessor)
.histogramCategoricalBy(groupBy);
.histogramCategorical(groupBy);
const occupancy = occupancyMap.get(categoryValue);
if (occupancy && occupancy.size > 0) {
// not all categories have occupancy, so occupancy may be undefined.
const x = d3
@@ -116,15 +106,18 @@ class Occupancy extends React.PureComponent {
.range([0, this._WIDTH]);
const categories =
schema.annotations.obsByName[colorAccessor]?.categories;
let currentOffset = 0;
const dfColumn = colorData.col(colorAccessor);
const categoryValues = dfColumn.summarizeCategorical().categories;
let o;
let scaledValue;
let value;
for (let i = 0, { length } = categoryValues; i < length; i += 1) {
value = categoryValues[i];
o = occupancy.get(value) as number;
o = occupancy.get(value);
scaledValue = x(o);
ctx.fillStyle = o
? colorScale(categories.indexOf(value))
@@ -135,13 +128,12 @@ class Occupancy extends React.PureComponent {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
const { colorAccessor, categoryValue, colorByIsCategorical } = this.props;
const { canvas } = this;
if (canvas)
canvas.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT);
return (
<Popover
interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}
@@ -0,0 +1,32 @@
/* rc slider https://www.npmjs.com/package/rc-slider */
import React from "react";
import { connect } from "react-redux";
import HistogramBrush from "../brushableHistogram";
@connect((state) => ({
schema: state.annoMatrix?.schema,
}))
class Continuous extends React.PureComponent {
render() {
/* initial value for iterator to simulate index, ranges is an object */
const { schema } = this.props;
if (!schema) return null;
const obsIndex = schema.annotations.obs.index;
const allContinuousNames = schema.annotations.obs.columns
.filter((col) => col.type === "int32" || col.type === "float32")
.filter((col) => col.name !== obsIndex)
.filter((col) => !col.writable) // skip user annotations - they will be treated as categorical
.map((col) => col.name);
return (
<div>
{allContinuousNames.map((key, zebra) => (
<HistogramBrush key={key} field={key} isObs zebra={zebra % 2 === 0} />
))}
</div>
);
}
}
export default Continuous;
@@ -1,41 +0,0 @@
/* rc slider https://www.npmjs.com/package/rc-slider */
import React from "react";
import { connect } from "react-redux";
import HistogramBrush from "../brushableHistogram";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
}))
class Continuous extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
/* initial value for iterator to simulate index, ranges is an object */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
const { schema } = this.props;
if (!schema) return null;
const obsIndex = schema.annotations.obs.index;
const allContinuousNames = schema.annotations.obs.columns
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((col: any) => col.type === "int32" || col.type === "float32")
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((col: any) => col.name !== obsIndex)
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((col: any) => !col.writable) // skip user annotations - they will be treated as categorical
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.map((col: any) => col.name);
return (
<div>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{allContinuousNames.map((key: any, zebra: any) => (
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
<HistogramBrush key={key} field={key} isObs zebra={zebra % 2 === 0} />
))}
</div>
);
}
}
export default Continuous;
@@ -5,8 +5,7 @@
******************************************/
import * as d3 from "d3";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
const setupParallelCoordinates = (width: any, height: any, margin: any) => {
const setupParallelCoordinates = (width, height, margin) => {
const container = d3.select("#parcoords");
const svg = container
@@ -25,15 +24,10 @@ const setupParallelCoordinates = (width: any, height: any, margin: any) => {
.style("margin-top", `${margin.top}px`)
.style("margin-left", `${margin.left}px`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const ctx = canvas.node().getContext("2d");
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.globalCompositeOperation = "darken";
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.globalAlpha = 0.15;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.lineWidth = 1.5;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.scale(devicePixelRatio, devicePixelRatio);
return {
+49
View File
@@ -0,0 +1,49 @@
import each from "lodash.foreach";
import * as d3 from "d3";
const paddingRight = 120;
const continuousChartWidth = 1200;
export const margin = { top: 66, right: 110, bottom: 20, left: 60 };
export const width =
continuousChartWidth - margin.left - margin.right - paddingRight;
export const height = 340 - margin.top - margin.bottom;
export const innerHeight = height - 2;
export const devicePixelRatio = window.devicePixelRatio || 1;
export const createDimensions = (data) => {
const newArr = [];
each(data, (value, key) => {
if (value.range) {
newArr.push({
key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */,
type: {
within: (d, extent, dim) =>
extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1],
},
scale: d3
.scaleSqrt()
.range([innerHeight, 0])
.domain([0, value.range.max]),
});
}
});
return newArr;
};
export const yAxis = d3.axisLeft();
export const brushstart = () => {
d3.event.sourceEvent.stopPropagation();
};
// Unused.
// export const d3_functor = v => (typeof v === "function" ? v : () => v);
export const project = (d, dimensions, xscale) =>
dimensions.map((p, i) => {
// check if data element has property and contains a value
if (!(p.key in d) || d[p.key] === null) return null;
return [xscale(i), p.scale(d[p.key])];
});
-57
View File
@@ -1,57 +0,0 @@
import each from "lodash.foreach";
import * as d3 from "d3";
const paddingRight = 120;
const continuousChartWidth = 1200;
export const margin = { top: 66, right: 110, bottom: 20, left: 60 };
export const width =
continuousChartWidth - margin.left - margin.right - paddingRight;
export const height = 340 - margin.top - margin.bottom;
export const innerHeight = height - 2;
export const devicePixelRatio = window.devicePixelRatio || 1;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const createDimensions = (data: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const newArr: any = [];
each(data, (value, key) => {
if (value.range) {
newArr.push({
key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */,
type: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
within: (d: any, extent: any, dim: any) =>
extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1],
},
scale: d3
.scaleSqrt()
.range([innerHeight, 0])
.domain([0, value.range.max]),
});
}
});
return newArr;
};
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
export const yAxis = d3.axisLeft();
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export const brushstart = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(d3 as any).event.sourceEvent.stopPropagation();
};
// Unused.
// export const d3_functor = v => (typeof v === "function" ? v : () => v);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const project = (d: any, dimensions: any, xscale: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
dimensions.map((p: any, i: any) => {
// check if data element has property and contains a value
if (!(p.key in d) || d[p.key] === null) return null;
return [xscale(i), p.scale(d[p.key])];
});
@@ -9,8 +9,7 @@ import {
} from "../../util/stateManager/colorHelpers";
// create continuous color legend
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
const continuous = (selectorId, colorScale, colorAccessor) => {
const legendHeight = 200;
const legendWidth = 80;
const margin = { top: 10, right: 60, bottom: 10, left: 2 };
@@ -34,7 +33,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
we flip the color scale as well [1, 0] instead of [0, 1] */
.node();
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const ctx = canvas.getContext("2d");
const legendScale = d3
@@ -46,7 +44,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
]); /* we flip this to make viridis colors dark if high in the color scale */
// image data hackery based on http://bl.ocks.org/mbostock/048d21cf747371b11884f75ad896e5a5
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const image = ctx.createImageData(1, legendHeight);
d3.range(legendHeight).forEach((i) => {
const c = d3.rgb(colorScale(legendScale.invert(i)));
@@ -55,7 +52,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
image.data[4 * i + 2] = c.b;
image.data[4 * i + 3] = 255;
});
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.putImageData(image, 0, 0);
// A simpler way to do the above, but possibly slower. keep in mind the legend
@@ -109,30 +105,27 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
.text(colorAccessor);
};
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
annoMatrix: state.annoMatrix,
colors: state.colors,
genesets: state.genesets.genesets,
}))
class ContinuousLegend extends React.Component {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
async componentDidUpdate(prevProps: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
async componentDidUpdate(prevProps) {
const { annoMatrix, colors, genesets } = this.props;
if (!colors || !annoMatrix) return;
if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) {
const { schema } = annoMatrix;
const { colorMode, colorAccessor, userColors } = colors;
const colorQuery = createColorQuery(
colorMode,
colorAccessor,
schema,
genesets
);
const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null;
const colorTable = createColorTable(
colorMode,
@@ -141,19 +134,19 @@ class ContinuousLegend extends React.Component {
schema,
userColors
);
const colorScale = colorTable.scale;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'range' does not exist on type '((idx: an... Remove this comment to see the full error message
const range = colorScale?.range;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type '((idx: a... Remove this comment to see the full error message
const [domainMin, domainMax] = colorScale?.domain?.() ?? [0, 0];
/* always remove it, if it's not continuous we don't put it back. */
d3.select("#continuous_legend").selectAll("*").remove();
if (colorAccessor && colorScale && range && domainMin < domainMax) {
/* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */
if (range()[0][0] !== "#") {
continuous(
"#continuous_legend",
// @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type '((idx: a... Remove this comment to see the full error message
d3.scaleSequential(interpolateCool).domain(colorScale.domain()),
colorAccessor
);
@@ -162,7 +155,6 @@ class ContinuousLegend extends React.Component {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
return (
<div
@@ -15,36 +15,23 @@ import * as globals from "../../globals";
import actions from "../../actions";
import { getDiscreteCellEmbeddingRowIndex } from "../../util/stateManager/viewStackHelpers";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type EmbeddingState = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
layoutChoice: (state as any).layoutChoice,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
crossfilter: (state as any).obsCrossfilter,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Embedding extends React.PureComponent<{}, EmbeddingState> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
layoutChoice: state.layoutChoice, // TODO: really should clean up naming, s/layout/embedding/g
schema: state.annoMatrix?.schema,
crossfilter: state.obsCrossfilter,
}))
class Embedding extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleLayoutChoiceChange = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleLayoutChoiceChange = (e) => {
const { dispatch } = this.props;
dispatch(actions.layoutChoiceAction(e.currentTarget.value));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on type 'Re... Remove this comment to see the full error message
const { layoutChoice, schema, crossfilter } = this.props;
const { annoMatrix } = crossfilter;
return (
@@ -111,23 +98,18 @@ class Embedding extends React.PureComponent<{}, EmbeddingState> {
export default Embedding;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const loadAllEmbeddingCounts = async ({ annoMatrix, available }: any) => {
const loadAllEmbeddingCounts = async ({ annoMatrix, available }) => {
const embeddings = await Promise.all(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
available.map((name: any) => annoMatrix.base().fetch("emb", name))
available.map((name) => annoMatrix.base().fetch("emb", name))
);
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
return available.map((name, idx) => ({
embeddingName: name,
embedding: embeddings[idx],
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable...
discreteCellIndex: getDiscreteCellEmbeddingRowIndex(embeddings[idx]),
}));
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => {
const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }) => {
const { available } = layoutChoice;
const { data, error, isPending } = useAsync({
promiseFn: loadAllEmbeddingCounts,
@@ -143,8 +125,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => {
/* still loading, or errored out - just omit counts (TODO: spinner?) */
return (
<RadioGroup onChange={onChange} selectedValue={layoutChoice.current}>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{layoutChoice.available.map((name: any) => (
{layoutChoice.available.map((name) => (
<Radio label={`${name}`} value={name} key={name} />
))}
</RadioGroup>
@@ -153,8 +134,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => {
if (data) {
return (
<RadioGroup onChange={onChange} selectedValue={layoutChoice.current}>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{data.map((summary: any) => {
{data.map((summary) => {
const { discreteCellIndex, embeddingName } = summary;
const sizeHint = `${discreteCellIndex.size()} cells`;
return (
@@ -1,7 +1,6 @@
import React from "react";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
function Container(props: any) {
function Container(props) {
const { children } = props;
return (
<div
@@ -2,8 +2,6 @@ import React from "react";
import * as globals from "../../globals";
class Layout extends React.Component {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
viewportRef: any;
/*
Layout - this react component contains all the layout style and logic for the application once it has loaded.
@@ -15,7 +13,6 @@ class Layout extends React.Component {
should be.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
/*
This is a bit of a hack. In order for the graph to size correctly, it needs to know the size of the parent
@@ -24,10 +21,8 @@ class Layout extends React.Component {
this.forceUpdate();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { children } = this.props;
// @ts-expect-error ts-migrate(2488) FIXME: Type 'ReactNode' must have a '[Symbol.iterator]()'... Remove this comment to see the full error message
const [leftSidebar, renderGraph, rightSidebar] = children;
return (
<div
@@ -1,8 +1,7 @@
import React from "react";
import * as globals from "../../globals";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
const Logo = (props: any) => {
const Logo = (props) => {
const { size } = props;
return (
<svg width={size} height={size} viewBox="0 0 48 48" fill="none">
@@ -0,0 +1,52 @@
import { Position, Toaster, Intent } from "@blueprintjs/core";
/** Singleton toaster instance. Create separate instances for different options. */
const ToastTopCenter = Toaster.create({
className: "recipe-toaster",
position: Position.TOP,
maxToasts: 4,
});
/*
A "user" error - eg, bad input
*/
export const postUserErrorToast = (message) =>
ToastTopCenter.show({ message, intent: Intent.WARNING });
/*
A toast the user must dismiss manually, because they need to act on its information,
ie., 8 bulk add genes out of 40 were bad. Manually see which ones and fix.
*/
export const keepAroundErrorToast = (message) =>
ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING });
/*
a hard network error
*/
export const postNetworkErrorToast = (message, key = undefined) =>
ToastTopCenter.show(
{
message,
timeout: 30000,
intent: Intent.DANGER,
},
key
);
/*
Async message to user
*/
export const postAsyncSuccessToast = (message) =>
ToastTopCenter.show({
message,
timeout: 10000,
intent: Intent.SUCCESS,
});
export const postAsyncFailureToast = (message) =>
ToastTopCenter.show({
message,
timeout: 10000,
intent: Intent.WARNING,
});
@@ -1,59 +0,0 @@
import { Position, Toaster, Intent } from "@blueprintjs/core";
/** Singleton toaster instance. Create separate instances for different options. */
const ToastTopCenter = Toaster.create({
className: "recipe-toaster",
position: Position.TOP,
maxToasts: 4,
});
/*
A "user" error - eg, bad input
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const postUserErrorToast = (message: any) =>
ToastTopCenter.show({ message, intent: Intent.WARNING });
/*
A toast the user must dismiss manually, because they need to act on its information,
ie., 8 bulk add genes out of 40 were bad. Manually see which ones and fix.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const keepAroundErrorToast = (message: any) =>
ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING });
/*
a hard network error
*/
export const postNetworkErrorToast = (
message: string,
key: string | undefined = undefined
): string =>
ToastTopCenter.show(
{
message,
timeout: 30000,
intent: Intent.DANGER,
},
key
);
/*
Async message to user
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const postAsyncSuccessToast = (message: any) =>
ToastTopCenter.show({
message,
timeout: 10000,
intent: Intent.SUCCESS,
});
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export const postAsyncFailureToast = (message: any) =>
ToastTopCenter.show({
message,
timeout: 10000,
intent: Intent.WARNING,
});
@@ -9,51 +9,34 @@ import actions from "../../actions";
const MINI_HISTOGRAM_WIDTH = 110;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state, ownProps) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'gene' does not exist on type '{}'.
const { gene } = ownProps;
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
isColorAccessor: (state as any).colors.colorAccessor === gene,
isScatterplotXXaccessor:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).controls.scatterplotXXaccessor === gene,
isScatterplotYYaccessor:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).controls.scatterplotYYaccessor === gene,
isColorAccessor: state.colors.colorAccessor === gene,
isScatterplotXXaccessor: state.controls.scatterplotXXaccessor === gene,
isScatterplotYYaccessor: state.controls.scatterplotYYaccessor === gene,
};
})
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Gene extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class Gene extends React.Component {
constructor(props) {
super(props);
this.state = {
geneIsExpanded: false,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
onColorChangeClick = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, gene } = this.props;
dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(gene));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleGeneExpandClick = () => {
const { geneIsExpanded } = this.state;
this.setState({ geneIsExpanded: !geneIsExpanded });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSetGeneAsScatterplotX = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, gene } = this.props;
dispatch({
type: "set scatterplot x",
@@ -61,9 +44,7 @@ class Gene extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSetGeneAsScatterplotY = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, gene } = this.props;
dispatch({
type: "set scatterplot y",
@@ -71,29 +52,19 @@ class Gene extends React.Component<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeleteGeneFromSet = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, gene, geneset } = this.props;
dispatch(actions.genesetDeleteGenes(geneset, [gene]));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'gene' does not exist on type 'Readonly<{... Remove this comment to see the full error message
gene,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'geneDescription' does not exist on type ... Remove this comment to see the full error message
geneDescription,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'quickGene' does not exist on type 'Reado... Remove this comment to see the full error message
quickGene,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'removeGene' does not exist on type 'Read... Remove this comment to see the full error message
removeGene,
} = this.props;
const { geneIsExpanded } = this.state;
@@ -113,7 +84,6 @@ class Gene extends React.Component<{}, State> {
>
<div
role="menuitem"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="0"
data-testclass="gene-expand"
data-testid={`${gene}:gene-expand`}
@@ -154,7 +124,6 @@ class Gene extends React.Component<{}, State> {
</div>
{!geneIsExpanded ? (
<HistogramBrush
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
isUserDefined
field={gene}
mini
@@ -219,7 +188,6 @@ class Gene extends React.Component<{}, State> {
/>
</div>
</div>
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
{geneIsExpanded && <HistogramBrush isUserDefined field={gene} />}
</div>
);
@@ -9,28 +9,20 @@ import HistogramBrush from "../brushableHistogram";
import { diffexpPopNamePrefix1, diffexpPopNamePrefix2 } from "../../globals";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class GeneSet extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class GeneSet extends React.Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
onGenesetMenuClick = () => {
const { isOpen } = this.state;
this.setState({ isOpen: !isOpen });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderGenes() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'setName' does not exist on type 'Readonl... Remove this comment to see the full error message
const { setName, setGenes } = this.props;
const setGenesNames = [...setGenes.keys()];
return (
@@ -40,7 +32,6 @@ class GeneSet extends React.Component<{}, State> {
return (
<Gene
key={gene}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: any; gene: any; geneDescription: any;... Remove this comment to see the full error message
gene={gene}
geneDescription={geneDescription}
geneset={setName}
@@ -51,9 +42,7 @@ class GeneSet extends React.Component<{}, State> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'setName' does not exist on type 'Readonl... Remove this comment to see the full error message
const { setName, genesetDescription, setGenes } = this.props;
const { isOpen } = this.state;
const genesetNameLengthVisible = 150; /* this magic number determines how much of a long geneset name we see */
@@ -76,7 +65,6 @@ class GeneSet extends React.Component<{}, State> {
>
<span
role="menuitem"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="0"
data-testclass={testClass}
data-testid={`${setName}:geneset-expand`}
@@ -117,7 +105,6 @@ class GeneSet extends React.Component<{}, State> {
)}
</span>
<div>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ isOpen: any; genesetsEditable: true; genes... Remove this comment to see the full error message */}
<GenesetMenus isOpen={isOpen} genesetsEditable geneset={setName} />
</div>
</div>
@@ -131,7 +118,6 @@ class GeneSet extends React.Component<{}, State> {
</div>
{isOpen && !genesetIsEmpty && (
<HistogramBrush
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
isGeneSetSummary
field={setName}
setGenes={setGenes}
@@ -139,7 +125,6 @@ class GeneSet extends React.Component<{}, State> {
)}
{isOpen && !genesetIsEmpty && this.renderGenes()}
<EditGenesetNameDialogue
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ parentGeneset: any; parentGenesetDescripti... Remove this comment to see the full error message
parentGeneset={setName}
parentGenesetDescription={genesetDescription}
/>
@@ -7,33 +7,23 @@ import GeneSet from "./geneSet";
import QuickGene from "./quickGene";
import CreateGenesetDialogue from "./menus/createGenesetDialogue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class GeneExpression extends React.Component<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
genesets: state.genesets.genesets,
}))
class GeneExpression extends React.Component {
constructor(props) {
super(props);
this.state = { geneSetsExpanded: true };
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderGeneSets = () => {
const sets = [];
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
const { genesets } = this.props;
for (const [name, geneset] of genesets) {
sets.push(
<GeneSet
key={name}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: any; setGenes: any; setName: any; gen... Remove this comment to see the full error message
setGenes={geneset.genes}
setName={name}
genesetDescription={geneset.genesetDescription}
@@ -43,28 +33,19 @@ class GeneExpression extends React.Component<{}, State> {
return sets;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleActivateCreateGenesetMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
const { geneSetsExpanded } = this.state;
dispatch({ type: "geneset: activate add new geneset mode" });
if (!geneSetsExpanded) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({ ...state, geneSetsExpanded: true }));
this.setState((state) => ({ ...state, geneSetsExpanded: true }));
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleExpandGeneSets = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({
...state,
geneSetsExpanded: !state.geneSetsExpanded,
}));
this.setState((state) => ({ ...state, geneSetsExpanded: !state.geneSetsExpanded }));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { geneSetsExpanded } = this.state;
return (
@@ -80,7 +61,6 @@ class GeneExpression extends React.Component<{}, State> {
>
<H4
role="menuitem"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="0"
data-testclass="geneset-heading-expand"
onKeyPress={this.handleExpandGeneSets}
@@ -0,0 +1,89 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import parseBulkGeneString from "../../../util/parseBulkGeneString";
import actions from "../../../actions";
@connect((state) => ({
genesetsUI: state.genesetsUI,
}))
class AddGeneToGenesetDialogue extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
genesToAdd: "",
};
}
disableAddGeneMode = () => {
const { dispatch } = this.props;
dispatch({
type: "geneset: disable add new genes mode",
});
};
handleAddGeneToGeneSet = (e) => {
const { geneset, dispatch } = this.props;
const { genesToAdd } = this.state;
const genesTmpHardcodedFormat = [];
const genesArrayFromString = parseBulkGeneString(genesToAdd);
genesArrayFromString.forEach((_gene) => {
genesTmpHardcodedFormat.push({
geneSymbol: _gene,
});
});
dispatch(actions.genesetAddGenes(geneset, genesTmpHardcodedFormat));
dispatch({
type: "geneset: disable add new genes mode",
});
if (e) e.preventDefault();
};
handleChange = (e) => {
this.setState({ genesToAdd: e });
};
render() {
const { geneset, genesetsUI } = this.props;
const { genesToAdd } = this.state;
return (
<>
<AnnoDialog
isActive={genesetsUI.isAddingGenesToGeneset === geneset}
inputProps={{ "data-testid": `${geneset}:create-label-dialog` }}
primaryButtonProps={{
"data-testid": `${geneset}:submit-gene`,
}}
title="Add genes to gene set"
instruction={`Add genes to ${geneset}`}
cancelTooltipContent="Close this dialog without adding genes to gene set."
primaryButtonText="Add genes"
text={genesToAdd}
validationError={false}
annoInput={
<LabelInput
onChange={this.handleChange}
inputProps={{
"data-testid": "add-genes",
leftIcon: "manually-entered-data",
intent: "none",
autoFocus: true,
}}
newLabelMessage="New category"
/>
}
handleSubmit={this.handleAddGeneToGeneSet}
handleCancel={this.disableAddGeneMode}
/>
</>
);
}
}
export default AddGeneToGenesetDialogue;
@@ -1,101 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
import parseBulkGeneString from "../../../util/parseBulkGeneString";
import actions from "../../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesetsUI: (state as any).genesetsUI,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class AddGeneToGenesetDialogue extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
genesToAdd: "",
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
disableAddGeneMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({
type: "geneset: disable add new genes mode",
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleAddGeneToGeneSet = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message
const { geneset, dispatch } = this.props;
const { genesToAdd } = this.state;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const genesTmpHardcodedFormat: any = [];
const genesArrayFromString = parseBulkGeneString(genesToAdd);
genesArrayFromString.forEach((_gene) => {
genesTmpHardcodedFormat.push({
geneSymbol: _gene,
});
});
dispatch(actions.genesetAddGenes(geneset, genesTmpHardcodedFormat));
dispatch({
type: "geneset: disable add new genes mode",
});
if (e) e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChange = (e: any) => {
this.setState({ genesToAdd: e });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message
const { geneset, genesetsUI } = this.props;
const { genesToAdd } = this.state;
return (
<>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: boolean; inputProps: { "data-tes... Remove this comment to see the full error message
isActive={genesetsUI.isAddingGenesToGeneset === geneset}
inputProps={{ "data-testid": `${geneset}:create-label-dialog` }}
primaryButtonProps={{
"data-testid": `${geneset}:submit-gene`,
}}
title="Add genes to gene set"
instruction={`Add genes to ${geneset}`}
cancelTooltipContent="Close this dialog without adding genes to gene set."
primaryButtonText="Add genes"
text={genesToAdd}
validationError={false}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ onChange: (e: any) => void; inputProps: { ... Remove this comment to see the full error message
onChange={this.handleChange}
inputProps={{
"data-testid": "add-genes",
leftIcon: "manually-entered-data",
intent: "none",
autoFocus: true,
}}
newLabelMessage="New category"
/>
}
handleSubmit={this.handleAddGeneToGeneSet}
handleCancel={this.disableAddGeneMode}
/>
</>
);
}
}
export default AddGeneToGenesetDialogue;
@@ -19,10 +19,8 @@ import {
import { memoize } from "../../../util/dataframe/util";
import parseBulkGeneString from "../../../util/parseBulkGeneString";
import { Dataframe } from "../../../util/dataframe";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => {
const renderGene = (fuzzySortResult, { handleClick, modifiers }) => {
if (!modifiers.matchesPredicate) {
return null;
}
@@ -35,8 +33,8 @@ const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => {
disabled={modifiers.disabled}
data-testid={`suggest-menu-item-${geneName}`}
key={geneName}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
onClick={(g: any /* this fires when user clicks a menu item */) =>
onClick={(g) =>
/* this fires when user clicks a menu item */
handleClick(g)
}
text={geneName}
@@ -44,30 +42,20 @@ const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => {
);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const filterGenes = (query: any, genes: any) =>
const filterGenes = (query, genes) =>
/* fires on load, once, and then for each character typed into the input */
fuzzysort.go(query, genes, {
limit: 5,
threshold: -10000, // don't return bad results
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type AddGenesState = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenes: (state as any).controls.userDefinedGenes,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenesLoading: (state as any).controls.userDefinedGenesLoading,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class AddGenes extends React.Component<{}, AddGenesState> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
annoMatrix: state.annoMatrix,
userDefinedGenes: state.controls.userDefinedGenes,
userDefinedGenesLoading: state.controls.userDefinedGenesLoading,
}))
class AddGenes extends React.Component {
constructor(props) {
super(props);
this.state = {
bulkAdd: "",
@@ -78,20 +66,15 @@ class AddGenes extends React.Component<{}, AddGenesState> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
this.updateState();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
componentDidUpdate(prevProps: {}) {
componentDidUpdate(prevProps) {
this.updateState(prevProps);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleClick(g: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleClick(g) {
const { dispatch, userDefinedGenes } = this.props;
const { geneNames } = this.state;
if (!g) return;
@@ -111,8 +94,7 @@ class AddGenes extends React.Component<{}, AddGenesState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
_genesToUpper = (listGenes: any) => {
_genesToUpper = (listGenes) => {
// Has to be a Map to preserve index
const upperGenes = new Map();
for (let i = 0, { length } = listGenes; i < length; i += 1) {
@@ -122,12 +104,10 @@ class AddGenes extends React.Component<{}, AddGenesState> {
return upperGenes;
};
// eslint-disable-next-line react/sort-comp, @typescript-eslint/no-explicit-any -- memo requires a defined _genesToUpper
_memoGenesToUpper = memoize(this._genesToUpper, (arr: any) => arr);
// eslint-disable-next-line react/sort-comp -- memo requires a defined _genesToUpper
_memoGenesToUpper = memoize(this._genesToUpper, (arr) => arr);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBulkAddClick = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, userDefinedGenes } = this.props;
const { bulkAdd, geneNames } = this.state;
@@ -177,9 +157,7 @@ class AddGenes extends React.Component<{}, AddGenesState> {
return undefined;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
async updateState(prevProps: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
async updateState(prevProps) {
const { annoMatrix } = this.props;
if (!annoMatrix) return;
if (annoMatrix !== prevProps?.annoMatrix) {
@@ -188,7 +166,7 @@ class AddGenes extends React.Component<{}, AddGenesState> {
this.setState({ status: "pending" });
try {
const df: Dataframe = await annoMatrix.fetch("var", varIndex);
const df = await annoMatrix.fetch("var", varIndex);
this.setState({
status: "success",
geneNames: df.col(varIndex).asArray(),
@@ -200,7 +178,6 @@ class AddGenes extends React.Component<{}, AddGenesState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
placeholderGeneNames() {
/*
return a string containing gene name suggestions for use as a user hint.
@@ -230,9 +207,7 @@ class AddGenes extends React.Component<{}, AddGenesState> {
return "Apod, Cd74, ...";
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'userDefinedGenesLoading' does not exist ... Remove this comment to see the full error message
const { userDefinedGenesLoading } = this.props;
const { tab, bulkAdd, activeItem, status, geneNames } = this.state;
@@ -288,10 +263,8 @@ class AddGenes extends React.Component<{}, AddGenesState> {
this.handleClick(g);
}}
initialContent={<MenuItem disabled text="Enter a gene…" />}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ "data-testid": string; }' is not assignabl... Remove this comment to see the full error message
inputProps={{ "data-testid": "gene-search" }}
inputValueRenderer={() => ""}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(query: any, genes: any) => Fuzzysort.Result... Remove this comment to see the full error message
itemListPredicate={filterGenes}
onActiveItemChange={(item) => this.setState({ activeItem: item })}
itemRenderer={renderGene}
@@ -7,26 +7,15 @@ import { Tooltip2 } from "@blueprintjs/popover2";
import LabelInput from "../../labelInput";
import actions from "../../../actions";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
obsCrossfilter: (state as any).obsCrossfilter,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesetsUI: (state as any).genesetsUI,
annotations: state.annotations,
schema: state.annoMatrix?.schema,
obsCrossfilter: state.obsCrossfilter,
genesets: state.genesets.genesets,
genesetsUI: state.genesetsUI,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class CreateGenesetDialogue extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class CreateGenesetDialogue extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
genesetName: "",
@@ -35,9 +24,7 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
disableCreateGenesetMode = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
disableCreateGenesetMode = (e) => {
const { dispatch } = this.props;
this.setState({
genesetName: "",
@@ -51,32 +38,30 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
if (e) e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
createGeneset = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
createGeneset = (e) => {
const { dispatch } = this.props;
const {
genesetName,
genesToPopulateGeneset,
genesetDescription,
} = this.state;
const { genesetName, genesToPopulateGeneset, genesetDescription } =
this.state;
dispatch({
type: "geneset: create",
genesetName: genesetName.trim(),
genesetDescription,
});
if (genesToPopulateGeneset) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const genesTmpHardcodedFormat: any = [];
const genesTmpHardcodedFormat = [];
const genesArrayFromString = pull(
uniq(genesToPopulateGeneset.split(/[ ,]+/)),
""
);
genesArrayFromString.forEach((_gene) => {
genesTmpHardcodedFormat.push({
geneSymbol: _gene,
});
});
dispatch(actions.genesetAddGenes(genesetName, genesTmpHardcodedFormat));
}
dispatch({
@@ -89,41 +74,34 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
genesetNameError = () => false;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChange = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
handleChange = (e) => {
const { genesets } = this.props;
this.setState({ genesetName: e });
this.validate(e, genesets);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleGenesetInputChange = (e: any) => {
handleGenesetInputChange = (e) => {
this.setState({ genesToPopulateGeneset: e });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleDescriptionInputChange = (e: any) => {
handleDescriptionInputChange = (e) => {
this.setState({ genesetDescription: e });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
instruction = (genesetName: any, genesets: any) =>
genesets.has(genesetName)
instruction = (genesetName, genesets) => genesets.has(genesetName)
? "Gene set name must be unique."
: "New, unique gene set name";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
validate = (genesetName: any, genesets: any) => {
validate = (genesetName, genesets) => {
if (genesets.has(genesetName)) {
this.setState({
nameErrorMessage: "There is already a geneset with that name",
});
return false;
}
if (
genesetName.length > 1 &&
// eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535
@@ -141,11 +119,10 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
return true;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { genesetName, nameErrorMessage } = this.state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetsUI' does not exist on type 'Read... Remove this comment to see the full error message
const { genesetsUI, genesets } = this.props;
return (
<>
<Dialog
@@ -163,7 +140,6 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
<div style={{ marginBottom: 20 }}>
<p>{this.instruction(genesetName, genesets)}</p>
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ onChange: (e: any) => void; inputProps: { ... Remove this comment to see the full error message
onChange={this.handleChange}
inputProps={{
"data-testid": "create-geneset-input",
@@ -188,7 +164,6 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
gene set
</p>
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ onChange: (e: any) => void; inputProps: { ... Remove this comment to see the full error message
onChange={this.handleDescriptionInputChange}
inputProps={{
"data-testid": "add-geneset-description",
@@ -204,7 +179,6 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> {
gene set
</p>
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ onChange: (e: any) => void; inputProps: { ... Remove this comment to see the full error message
onChange={this.handleGenesetInputChange}
inputProps={{
"data-testid": "add-genes",
@@ -0,0 +1,124 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
@connect((state) => ({
annotations: state.annotations,
schema: state.annoMatrix?.schema,
obsCrossfilter: state.obsCrossfilter,
genesetsUI: state.genesetsUI,
genesets: state.genesets.genesets,
}))
class RenameGeneset extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
newGenesetName: props.parentGeneset,
newGenesetDescription: props.parentGenesetDescription,
};
}
disableEditGenesetNameMode = (e) => {
const { dispatch } = this.props;
this.setState({
newGenesetName: "",
newGenesetDescription: "",
});
dispatch({
type: "geneset: disable rename geneset mode",
});
if (e) e.preventDefault();
};
renameGeneset = (e) => {
const { dispatch, genesetsUI } = this.props;
const { newGenesetName, newGenesetDescription } = this.state;
dispatch({
type: "geneset: update",
genesetName: genesetsUI.isEditingGenesetName,
update: {
genesetName: newGenesetName,
genesetDescription: newGenesetDescription,
},
});
dispatch({
type: "geneset: disable rename geneset mode",
});
e.preventDefault();
};
genesetNameError = () => false;
handleChange = (e) => {
this.setState({ newGenesetName: e });
};
handleChangeDescription = (e) => {
this.setState({ newGenesetDescription: e });
};
validate = (genesetName, genesets) => (
!genesets.has(genesetName) &&
// eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535
genesetName.match(/^\s|[\u0000-\u001F\u007F-\uFFFF]|[ ]{2,}|^$|\s$/g)
?.length
);
render() {
const { newGenesetName, newGenesetDescription } = this.state;
const { genesetsUI, parentGeneset, parentGenesetDescription, genesets } =
this.props;
return (
<>
<AnnoDialog
isActive={genesetsUI.isEditingGenesetName === parentGeneset}
inputProps={{
"data-testid": `${genesetsUI.isEditingGenesetName}:rename-geneset-dialog`,
}}
primaryButtonProps={{
"data-testid": `${genesetsUI.isEditingGenesetName}:submit-geneset`,
}}
title="Edit gene set name and description"
instruction={`Rename ${genesetsUI.isEditingGenesetName}`}
cancelTooltipContent="Close this dialog without renaming the gene set."
primaryButtonText="Edit gene set name and description"
text={newGenesetName}
secondaryText={newGenesetDescription}
validationError={
this.validate(newGenesetName, genesets) &&
parentGenesetDescription === newGenesetDescription
}
annoInput={
<LabelInput
label={newGenesetName}
onChange={this.handleChange}
inputProps={{
"data-testid": "rename-geneset-modal",
leftIcon: "manually-entered-data",
intent: "none",
autoFocus: true,
}}
/>
}
secondaryInstructions="Edit description"
secondaryInput={
<LabelInput
label={newGenesetDescription}
onChange={this.handleChangeDescription}
inputProps={{ "data-testid": "change geneset description" }}
intent="none"
autoFocus={false}
/>
}
handleSubmit={this.renameGeneset}
handleCancel={this.disableEditGenesetNameMode}
/>
</>
);
}
}
export default RenameGeneset;
@@ -1,154 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annotations: (state as any).annotations,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix?.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
obsCrossfilter: (state as any).obsCrossfilter,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesetsUI: (state as any).genesetsUI,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class RenameGeneset extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGeneset' does not exist on type '{... Remove this comment to see the full error message
newGenesetName: props.parentGeneset,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGenesetDescription' does not exist... Remove this comment to see the full error message
newGenesetDescription: props.parentGenesetDescription,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
disableEditGenesetNameMode = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
this.setState({
newGenesetName: "",
newGenesetDescription: "",
});
dispatch({
type: "geneset: disable rename geneset mode",
});
if (e) e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
renameGeneset = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, genesetsUI } = this.props;
const { newGenesetName, newGenesetDescription } = this.state;
dispatch({
type: "geneset: update",
genesetName: genesetsUI.isEditingGenesetName,
update: {
genesetName: newGenesetName,
genesetDescription: newGenesetDescription,
},
});
dispatch({
type: "geneset: disable rename geneset mode",
});
e.preventDefault();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
genesetNameError = () => false;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChange = (e: any) => {
this.setState({ newGenesetName: e });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChangeDescription = (e: any) => {
this.setState({ newGenesetDescription: e });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
validate = (genesetName: any, genesets: any) =>
!genesets.has(genesetName) &&
// eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535
genesetName.match(/^\s|[\u0000-\u001F\u007F-\uFFFF]|[ ]{2,}|^$|\s$/g)
?.length;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { newGenesetName, newGenesetDescription } = this.state;
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetsUI' does not exist on type 'Read... Remove this comment to see the full error message
genesetsUI,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGeneset' does not exist on type 'Read... Remove this comment to see the full error message
parentGeneset,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGenesetDescription' does not exist on type 'Read... Remove this comment to see the full error message
parentGenesetDescription,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Read... Remove this comment to see the full error message
genesets,
} = this.props;
return (
<>
<AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: boolean; inputProps: { "data-tes... Remove this comment to see the full error message
isActive={genesetsUI.isEditingGenesetName === parentGeneset}
inputProps={{
"data-testid": `${genesetsUI.isEditingGenesetName}:rename-geneset-dialog`,
}}
primaryButtonProps={{
"data-testid": `${genesetsUI.isEditingGenesetName}:submit-geneset`,
}}
title="Edit gene set name and description"
instruction={`Rename ${genesetsUI.isEditingGenesetName}`}
cancelTooltipContent="Close this dialog without renaming the gene set."
primaryButtonText="Edit gene set name and description"
text={newGenesetName}
secondaryText={newGenesetDescription}
validationError={
this.validate(newGenesetName, genesets) &&
parentGenesetDescription === newGenesetDescription
}
annoInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ label: any; onChange: (e: any) => void; in... Remove this comment to see the full error message
label={newGenesetName}
onChange={this.handleChange}
inputProps={{
"data-testid": "rename-geneset-modal",
leftIcon: "manually-entered-data",
intent: "none",
autoFocus: true,
}}
/>
}
secondaryInstructions="Edit description"
secondaryInput={
<LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ label: any; onChange: (e: any) => void; in... Remove this comment to see the full error message
label={newGenesetDescription}
onChange={this.handleChangeDescription}
inputProps={{ "data-testid": "change geneset description" }}
intent="none"
autoFocus={false}
/>
}
handleSubmit={this.renameGeneset}
handleCancel={this.disableEditGenesetNameMode}
/>
</>
);
}
}
export default RenameGeneset;
@@ -17,27 +17,17 @@ import * as globals from "../../../globals";
import actions from "../../../actions";
import AddGeneToGenesetDialogue from "./addGeneToGenesetDialogue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesetsUI: (state as any).genesetsUI,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colorAccessor: (state as any).colors.colorAccessor,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class GenesetMenus extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
genesetsUI: state.genesetsUI,
colorAccessor: state.colors.colorAccessor,
}))
class GenesetMenus extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
activateAddGeneToGenesetMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, geneset } = this.props;
dispatch({
type: "geneset: activate add new genes mode",
@@ -45,9 +35,7 @@ class GenesetMenus extends React.PureComponent<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
activateEditGenesetNameMode = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, geneset } = this.props;
dispatch({
@@ -56,9 +44,7 @@ class GenesetMenus extends React.PureComponent<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleColorByEntireGeneset = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, geneset } = this.props;
dispatch({
@@ -67,16 +53,12 @@ class GenesetMenus extends React.PureComponent<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeleteGeneset = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, geneset } = this.props;
dispatch(actions.genesetDelete(geneset));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message
const { geneset, genesetsEditable, createText, colorAccessor } = this.props;
const isColorBy = geneset === colorAccessor;
@@ -100,7 +82,6 @@ class GenesetMenus extends React.PureComponent<{}, State> {
minimal
/>
</Tooltip2>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ geneset: any; }' is not assignable to type... Remove this comment to see the full error message */}
<AddGeneToGenesetDialogue geneset={geneset} />
<Popover
interactionKind={PopoverInteractionKind.HOVER}
@@ -9,10 +9,8 @@ import Gene from "./gene";
import { postUserErrorToast } from "../framework/toasters";
import actions from "../../actions";
import { Dataframe, DataframeValue } from "../../util/dataframe";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const usePrevious = (value: any) => {
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
@@ -20,40 +18,34 @@ const usePrevious = (value: any) => {
return ref.current;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
function QuickGene() {
const dispatch = useDispatch();
const [isExpanded, setIsExpanded] = useState(true);
const [geneNames, setGeneNames] = useState([] as DataframeValue[]);
const [geneNames, setGeneNames] = useState([]);
const [, setStatus] = useState("pending");
const { annoMatrix, userDefinedGenes, userDefinedGenesLoading } = useSelector(
(state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenes: (state as any).controls.userDefinedGenes,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenesLoading: (state as any).controls.userDefinedGenesLoading,
})
annoMatrix: state.annoMatrix,
userDefinedGenes: state.controls.userDefinedGenes,
userDefinedGenesLoading: state.controls.userDefinedGenesLoading,
})
);
const prevProps = usePrevious({ annoMatrix });
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '() => Promise<void>' is not assi... Remove this comment to see the full error message
useEffect(async () => {
if (!annoMatrix) return;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
if (annoMatrix !== (prevProps as any)?.annoMatrix) {
if (annoMatrix !== prevProps?.annoMatrix) {
const { schema } = annoMatrix;
const varIndex = schema.annotations.var.index;
setStatus("pending");
try {
const df: Dataframe = await annoMatrix.fetch("var", varIndex);
const df = await annoMatrix.fetch("var", varIndex);
setStatus("success");
setGeneNames(df.col(varIndex).asArray() as DataframeValue[]);
setGeneNames(df.col(varIndex).asArray());
} catch (error) {
setStatus("error");
throw error;
@@ -63,12 +55,7 @@ function QuickGene() {
const handleExpand = () => setIsExpanded(!isExpanded);
const renderGene = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
fuzzySortResult: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
{ handleClick, modifiers }: any
) => {
const renderGene = (fuzzySortResult, { handleClick, modifiers }) => {
if (!modifiers.matchesPredicate) {
return null;
}
@@ -81,8 +68,8 @@ function QuickGene() {
disabled={modifiers.disabled}
data-testid={`suggest-menu-item-${geneName}`}
key={geneName}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
onClick={(g: any /* this fires when user clicks a menu item */) =>
onClick={(g) =>
/* this fires when user clicks a menu item */
handleClick(g)
}
text={geneName}
@@ -90,8 +77,7 @@ function QuickGene() {
);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const handleClick = (g: any) => {
const handleClick = (g) => {
if (!g) return;
const gene = g.target;
if (userDefinedGenes.indexOf(gene) !== -1) {
@@ -105,39 +91,30 @@ function QuickGene() {
}
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const filterGenes = (query: any, genes: any) =>
const filterGenes = (query, genes) =>
/* fires on load, once, and then for each character typed into the input */
fuzzysort.go(query, genes, {
limit: 5,
threshold: -10000, // don't return bad results
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const removeGene = (gene: any) => () => {
const removeGene = (gene) => () => {
dispatch({ type: "clear user defined gene", data: gene });
};
const QuickGenes = useMemo(
() =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenes.map((gene: any) => (
const QuickGenes = useMemo(() => userDefinedGenes.map((gene) => (
<Gene
key={`quick=${gene}`}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: string; gene: any; removeGene: (gene:... Remove this comment to see the full error message
gene={gene}
removeGene={removeGene}
quickGene
/>
)),
[userDefinedGenes]
);
)), [userDefinedGenes]);
return (
<div style={{ width: "100%", marginBottom: "16px" }}>
<H4
role="menuitem"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment to see the full error message
tabIndex="0"
data-testclass="quickgene-heading-expand"
onKeyPress={handleExpand}
@@ -168,14 +145,12 @@ function QuickGene() {
}}
initialContent={<MenuItem disabled text="Enter a gene…" />}
inputProps={{
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ "data-testid": string; placeholder: string... Remove this comment to see the full error message
"data-testid": "gene-search",
placeholder: "Quick Gene Search",
leftIcon: IconNames.SEARCH,
fill: true,
}}
inputValueRenderer={() => ""}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(query: any, genes: any) => Fuzzysort.Result... Remove this comment to see the full error message
itemListPredicate={filterGenes}
itemRenderer={renderGene}
items={geneNames || ["No genes"]}
@@ -1,7 +1,6 @@
import { glPointFlags, glPointSize } from "../../util/glHelpers";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export default function drawPointsRegl(regl: any) {
export default function drawPointsRegl(regl) {
return regl({
vert: `
precision mediump float;
@@ -26,7 +26,6 @@ import {
flagSelected,
flagHighlight,
} from "../../util/glHelpers";
import { Dataframe } from "../../util/dataframe";
/*
Simple 2D transforms control all point painting. There are three:
@@ -35,8 +34,7 @@ Simple 2D transforms control all point painting. There are three:
* camera - apply a 2D camera transformation (pan, zoom)
* projection - apply any transformation required for screen size and layout
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function createProjectionTF(viewportWidth: any, viewportHeight: any) {
function createProjectionTF(viewportWidth, viewportHeight) {
/*
the projection transform accounts for the screen size & other layout
*/
@@ -55,7 +53,6 @@ function createProjectionTF(viewportWidth: any, viewportHeight: any) {
0,
(bottomGutterSizePx - topGutterSizePx) / viewportHeight / aspectScale[1],
]);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
mat3.scale(m, m, aspectScale);
return m;
}
@@ -70,48 +67,32 @@ function createModelTF() {
return m;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type GraphState = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
crossfilter: (state as any).obsCrossfilter,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
selectionTool: (state as any).graphSelection.tool,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
currentSelection: (state as any).graphSelection.selection,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
layoutChoice: (state as any).layoutChoice,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
graphInteractionMode: (state as any).controls.graphInteractionMode,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
pointDilation: (state as any).pointDilation,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
annoMatrix: state.annoMatrix,
crossfilter: state.obsCrossfilter,
selectionTool: state.graphSelection.tool,
currentSelection: state.graphSelection.selection,
layoutChoice: state.layoutChoice,
graphInteractionMode: state.controls.graphInteractionMode,
colors: state.colors,
pointDilation: state.pointDilation,
genesets: state.genesets.genesets,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Graph extends React.Component<{}, GraphState> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static createReglState(canvas: any) {
class Graph extends React.Component {
static createReglState(canvas) {
/*
Must be created for each canvas
*/
Must be created for each canvas
*/
// setup canvas, webgl draw function and camera
const camera = _camera(canvas);
const regl = _regl(canvas);
const drawPoints = _drawPoints(regl);
// preallocate webgl buffers
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const pointBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const colorBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const flagBuffer = regl.buffer();
return {
camera,
regl,
@@ -122,21 +103,14 @@ class Graph extends React.Component<{}, GraphState> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
cachedAsyncProps: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
reglCanvas: any;
computePointPositions = memoize((X, Y, modelTF) => {
/*
compute the model coordinate for each point
*/
compute the model coordinate for each point
*/
const positions = new Float32Array(2 * X.length);
for (let i = 0, len = X.length; i < len; i += 1) {
const p = vec2.fromValues(X[i], Y[i]);
@@ -149,8 +123,8 @@ class Graph extends React.Component<{}, GraphState> {
computePointColors = memoize((rgb) => {
/*
compute webgl colors for each point
*/
compute webgl colors for each point
*/
const colors = new Float32Array(3 * rgb.length);
for (let i = 0, len = rgb.length; i < len; i += 1) {
colors.set(rgb[i], 3 * i);
@@ -199,20 +173,21 @@ class Graph extends React.Component<{}, GraphState> {
computePointFlags = memoize(
(crossfilter, colorByData, pointDilationData, pointDilationLabel) => {
/*
We communicate with the shader using three flags:
- isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor
- isSelected -- the value is selected
- isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting)
Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda"
like bitmasks.
We also have separate code paths for generating flags for categorical and
continuous metadata, as they rely on different tests, and some of the flags
(eg, isNaN) are meaningless in the face of categorical metadata.
*/
We communicate with the shader using three flags:
- isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor
- isSelected -- the value is selected
- isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting)
Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda"
like bitmasks.
We also have separate code paths for generating flags for categorical and
continuous metadata, as they rely on different tests, and some of the flags
(eg, isNaN) are meaningless in the face of categorical metadata.
*/
const nObs = crossfilter.size();
const flags = new Float32Array(nObs);
const selectedFlags = this.computeSelectedFlags(
crossfilter,
flagSelected,
@@ -224,15 +199,16 @@ class Graph extends React.Component<{}, GraphState> {
pointDilationLabel
);
const colorByFlags = this.computeColorByFlags(nObs, colorByData);
for (let i = 0; i < nObs; i += 1) {
flags[i] = selectedFlags[i] + highlightFlags[i] + colorByFlags[i];
}
return flags;
}
);
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
const viewport = this.getViewportDimensions();
this.reglCanvas = null;
@@ -243,18 +219,20 @@ class Graph extends React.Component<{}, GraphState> {
tool: null,
container: null,
viewport,
// projection
camera: null,
modelTF,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '[]' is not assignable to paramet... Remove this comment to see the full error message
modelInvTF: mat3.invert([], modelTF),
projectionTF: createProjectionTF(viewport.width, viewport.height),
// regl state
regl: null,
drawPoints: null,
pointBuffer: null,
colorBuffer: null,
flagBuffer: null,
// component rendering derived state - these must stay synchronized
// with the reducer state they were generated from.
layoutState: {
@@ -273,32 +251,23 @@ class Graph extends React.Component<{}, GraphState> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
window.addEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
componentDidUpdate(prevProps: {}, prevState: GraphState) {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
selectionTool,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type 'R... Remove this comment to see the full error message
currentSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on type 'R... Remove this comment to see the full error message
graphInteractionMode,
} = this.props;
componentDidUpdate(prevProps, prevState) {
const { selectionTool, currentSelection, graphInteractionMode } =
this.props;
const { toolSVG, viewport } = this.state;
const hasResized =
prevState.viewport.height !== viewport.height ||
prevState.viewport.width !== viewport.width;
let stateChanges = {};
if (
(viewport.height && viewport.width && !toolSVG) || // first time init
hasResized || // window size has changed we want to recreate all SVGs
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type '{... Remove this comment to see the full error message
selectionTool !== prevProps.selectionTool || // change of selection tool
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
prevProps.graphInteractionMode !== graphInteractionMode // lasso/zoom mode is switched
) {
stateChanges = {
@@ -306,23 +275,19 @@ class Graph extends React.Component<{}, GraphState> {
...this.createToolSVG(),
};
}
/*
if the selection tool or state has changed, ensure that the selection
tool correctly reflects the underlying selection.
*/
if the selection tool or state has changed, ensure that the selection
tool correctly reflects the underlying selection.
*/
if (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
currentSelection !== prevProps.currentSelection ||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
graphInteractionMode !== prevProps.graphInteractionMode ||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'toolSVG' does not exist on type '{}'.
stateChanges.toolSVG
) {
const { tool, container } = this.state;
this.selectionToolUpdate(
// @ts-expect-error ts-migrate(2339) FIXME: Property 'tool' does not exist on type '{}'.
stateChanges.tool ? stateChanges.tool : tool,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'container' does not exist on type '{}'.
stateChanges.container ? stateChanges.container : container
);
}
@@ -332,12 +297,10 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleResize = () => {
const { state } = this.state;
const viewport = this.getViewportDimensions();
@@ -349,35 +312,27 @@ class Graph extends React.Component<{}, GraphState> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCanvasEvent = (e: any) => {
handleCanvasEvent = (e) => {
const { camera, projectionTF } = this.state;
if (e.type !== "wheel") e.preventDefault();
if (camera.handleEvent(e, projectionTF)) {
this.renderCanvas();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({
...state,
updateOverlay: !state.updateOverlay,
}));
this.setState((state) => ({ ...state, updateOverlay: !state.updateOverlay }));
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushDragAction() {
/*
event describing brush position:
@-------|
| |
| |
|-------@
*/
event describing brush position:
@-------|
| |
| |
|-------@
*/
// ignore programatically generated events
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (d3.event.sourceEvent === null || !d3.event.selection) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
const s = d3.event.selection;
const northwest = this.mapScreenToPoint(s[0]);
const southeast = this.mapScreenToPoint(s[1]);
@@ -395,28 +350,23 @@ class Graph extends React.Component<{}, GraphState> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushStartAction() {
// Ignore programatically generated events.
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (!d3.event.sourceEvent) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch(actions.graphBrushStartAction());
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushEndAction() {
// Ignore programatically generated events.
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (!d3.event.sourceEvent) return;
/*
coordinates will be included if selection made, null
if selection cleared.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
coordinates will be included if selection made, null
if selection cleared.
*/
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
const s = d3.event.selection;
if (s) {
const northwest = this.mapScreenToPoint(s[0]);
@@ -438,27 +388,21 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphBrushDeselectAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoStart() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
dispatch(actions.graphLassoStartAction(layoutChoice.current));
}
// when a lasso is completed, filter to the points within the lasso polygon
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleLassoEnd(polygon: any) {
handleLassoEnd(polygon) {
const minimumPolygonArea = 10;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
if (
polygon.length < 3 ||
Math.abs(d3.polygonArea(polygon)) < minimumPolygonArea
@@ -469,38 +413,29 @@ class Graph extends React.Component<{}, GraphState> {
dispatch(
actions.graphLassoEndAction(
layoutChoice.current,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
polygon.map((xy: any) => this.mapScreenToPoint(xy))
polygon.map((xy) => this.mapScreenToPoint(xy))
)
);
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoCancel() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphLassoCancelAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphLassoDeselectAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
const { selectionTool } = this.props;
if (selectionTool === "brush") this.handleBrushDeselectAction();
if (selectionTool === "lasso") this.handleLassoDeselectAction();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleOpacityRangeChange(e: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleOpacityRangeChange(e) {
const { dispatch } = this.props;
dispatch({
type: "change opacity deselected cells in 2d graph background",
@@ -508,17 +443,14 @@ class Graph extends React.Component<{}, GraphState> {
});
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
setReglCanvas = (canvas: any) => {
setReglCanvas = (canvas) => {
this.reglCanvas = canvas;
this.setState({
...Graph.createReglState(canvas),
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getViewportDimensions = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'viewportRef' does not exist on type 'Rea... Remove this comment to see the full error message
const { viewportRef } = this.props;
return {
height: viewportRef.clientHeight,
@@ -526,19 +458,19 @@ class Graph extends React.Component<{}, GraphState> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
createToolSVG = () => {
/*
Called from componentDidUpdate. Create the tool SVG, and return any
state changes that should be passed to setState().
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
Called from componentDidUpdate. Create the tool SVG, and return any
state changes that should be passed to setState().
*/
const { selectionTool, graphInteractionMode } = this.props;
const { viewport } = this.state;
/* clear out whatever was on the div, even if nothing, but usually the brushes etc */
const lasso = d3.select("#lasso-layer");
if (lasso.empty()) return {}; // still initializing
lasso.selectAll(".lasso-group").remove();
// Don't render or recreate toolSVG if currently in zoom mode
if (graphInteractionMode !== "select") {
// don't return "change" of state unless we are really changing it!
@@ -546,6 +478,7 @@ class Graph extends React.Component<{}, GraphState> {
if (toolSVG === undefined) return {};
return { toolSVG: undefined };
}
let handleStart;
let handleDrag;
let handleEnd;
@@ -559,6 +492,7 @@ class Graph extends React.Component<{}, GraphState> {
handleEnd = this.handleLassoEnd.bind(this);
handleCancel = this.handleLassoCancel.bind(this);
}
const {
svg: newToolSVG,
tool,
@@ -571,11 +505,11 @@ class Graph extends React.Component<{}, GraphState> {
handleCancel,
viewport
);
return { toolSVG: newToolSVG, tool, container };
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
fetchAsyncProps = async (props) => {
const {
annoMatrix,
colors: colorsProp,
@@ -585,19 +519,24 @@ class Graph extends React.Component<{}, GraphState> {
viewport,
} = props.watchProps;
const { modelTF } = this.state;
const [layoutDf, colorDf, pointDilationDf] = await this.fetchData(
annoMatrix,
layoutChoice,
colorsProp,
pointDilation
);
const { currentDimNames } = layoutChoice;
const X = layoutDf.col(currentDimNames[0]).asArray();
const Y = layoutDf.col(currentDimNames[1]).asArray();
const positions = this.computePointPositions(X, Y, modelTF);
const colorTable = this.updateColorTable(colorsProp, colorDf);
const colors = this.computePointColors(colorTable.rgb);
const colorByData = colorDf?.icol(0)?.asArray();
const { colorAccessor } = colorsProp;
const colorByData = colorDf?.col(colorAccessor)?.asArray();
const {
metadataField: pointDilationCategory,
categoryField: pointDilationLabel,
@@ -611,6 +550,7 @@ class Graph extends React.Component<{}, GraphState> {
pointDilationData,
pointDilationLabel
);
const { width, height } = viewport;
return {
positions,
@@ -621,53 +561,50 @@ class Graph extends React.Component<{}, GraphState> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async fetchData(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
annoMatrix: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
layoutChoice: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colors: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointDilation: any
): Promise<[Dataframe, Dataframe | null, Dataframe | null]> {
async fetchData(annoMatrix, layoutChoice, colors, pointDilation) {
/*
fetch all data needed. Includes:
- the color by dataframe
- the layout dataframe
- the point dilation dataframe
*/
fetch all data needed. Includes:
- the color by dataframe
- the layout dataframe
- the point dilation dataframe
*/
const { metadataField: pointDilationAccessor } = pointDilation;
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// color
const query = this.createColorByQuery(colors);
const promises: [
Promise<Dataframe>,
Promise<Dataframe | null>,
Promise<Dataframe | null>
] = [
annoMatrix.fetch("emb", layoutChoice.current),
query ? annoMatrix.fetch(...query) : Promise.resolve(null),
pointDilationAccessor
? annoMatrix.fetch("obs", pointDilationAccessor)
: Promise.resolve(null),
];
if (query) {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
// point highlighting
if (pointDilationAccessor) {
promises.push(annoMatrix.fetch("obs", pointDilationAccessor));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
brushToolUpdate(tool: any, container: any) {
brushToolUpdate(tool, container) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { currentSelection } = this.props;
if (container) {
const toolCurrentSelection = d3.brushSelection(container.node());
if (currentSelection.mode === "within-rect") {
/*
if there is a selection, make sure the brush tool matches
*/
if there is a selection, make sure the brush tool matches
*/
const screenCoords = [
this.mapPointToScreen(currentSelection.brushCoords.northwest),
this.mapPointToScreen(currentSelection.brushCoords.southeast),
@@ -682,7 +619,6 @@ class Graph extends React.Component<{}, GraphState> {
for (let x = 0; x < 2; x += 1) {
for (let y = 0; y < 2; y += 1) {
delta += Math.abs(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
screenCoords[x][y] - toolCurrentSelection[x][y]
);
}
@@ -698,20 +634,17 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
lassoToolUpdate(tool: any) {
lassoToolUpdate(tool) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { currentSelection } = this.props;
if (currentSelection.mode === "within-polygon") {
/*
if there is a current selection, make sure the lasso tool matches
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const polygon = currentSelection.polygon.map((p: any) =>
if there is a current selection, make sure the lasso tool matches
*/
const polygon = currentSelection.polygon.map((p) =>
this.mapPointToScreen(p)
);
tool.move(polygon);
@@ -720,20 +653,17 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
selectionToolUpdate(tool: any, container: any) {
selectionToolUpdate(tool, container) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { selectionTool } = this.props;
switch (selectionTool) {
case "brush":
this.brushToolUpdate(tool, container);
break;
case "lasso":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
this.lassoToolUpdate(tool, container);
break;
default:
@@ -742,17 +672,19 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
mapScreenToPoint(pin: any) {
mapScreenToPoint(pin) {
/*
Map an XY coordinates from screen domain to cell/point range,
accounting for current pan/zoom camera.
*/
Map an XY coordinates from screen domain to cell/point range,
accounting for current pan/zoom camera.
*/
const { camera, projectionTF, modelInvTF, viewport } = this.state;
const cameraInvTF = camera.invView();
/* screen -> gl */
const x = (2 * pin[0]) / viewport.width - 1;
const y = 2 * (1 - pin[1] / viewport.height) - 1;
const xy = vec2.fromValues(x, y);
const projectionInvTF = mat3.invert(mat3.create(), projectionTF);
vec2.transformMat3(xy, xy, projectionInvTF);
@@ -761,17 +693,19 @@ class Graph extends React.Component<{}, GraphState> {
return xy;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
mapPointToScreen(xyCell: any) {
mapPointToScreen(xyCell) {
/*
Map an XY coordinate from cell/point domain to screen range. Inverse
of mapScreenToPoint()
*/
Map an XY coordinate from cell/point domain to screen range. Inverse
of mapScreenToPoint()
*/
const { camera, projectionTF, modelTF, viewport } = this.state;
const cameraTF = camera.view();
const xy = vec2.transformMat3(vec2.create(), xyCell, modelTF);
vec2.transformMat3(xy, xy, cameraTF);
vec2.transformMat3(xy, xy, projectionTF);
return [
Math.round(((xy[0] + 1) * viewport.width) / 2),
Math.round(-((xy[1] + 1) / 2 - 1) * viewport.height),
@@ -799,12 +733,12 @@ class Graph extends React.Component<{}, GraphState> {
);
});
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateReglAndRender(asyncProps: any, prevAsyncProps: any) {
updateReglAndRender(asyncProps, prevAsyncProps) {
const { positions, colors, flags, height, width } = asyncProps;
this.cachedAsyncProps = asyncProps;
const { pointBuffer, colorBuffer, flagBuffer } = this.state;
let needToRenderCanvas = false;
if (height !== prevAsyncProps?.height || width !== prevAsyncProps?.width) {
needToRenderCanvas = true;
}
@@ -823,11 +757,10 @@ class Graph extends React.Component<{}, GraphState> {
if (needToRenderCanvas) this.renderCanvas();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateColorTable(colors: any, colorDf: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
updateColorTable(colors, colorDf) {
const { annoMatrix } = this.props;
const { schema } = annoMatrix;
/* update color table state */
if (!colors || !colorDf) {
return createColorTable(
@@ -838,6 +771,7 @@ class Graph extends React.Component<{}, GraphState> {
null
);
}
const { colorAccessor, userColors, colorMode } = colors;
return createColorTable(
colorMode,
@@ -848,35 +782,26 @@ class Graph extends React.Component<{}, GraphState> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
createColorByQuery(colors: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
createColorByQuery(colors) {
const { annoMatrix, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderPoints(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
regl: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
drawPoints: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
flagBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
camera: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
projectionTF: any
regl,
drawPoints,
colorBuffer,
pointBuffer,
flagBuffer,
camera,
projectionTF
) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix } = this.props;
if (!this.reglCanvas || !annoMatrix) return;
const { schema } = annoMatrix;
const cameraTF = camera.view();
const projView = mat3.multiply(mat3.create(), projectionTF, cameraTF);
@@ -899,24 +824,18 @@ class Graph extends React.Component<{}, GraphState> {
regl._gl.flush();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
graphInteractionMode,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on ... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on ... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on ... Remove this comment to see the full error message
layoutChoice,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on ... Remove this comment to see the full error message
pointDilation,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on ... Remove this comment to see the full error message
crossfilter,
} = this.props;
const { modelTF, projectionTF, camera, viewport, regl } = this.state;
const cameraTF = camera?.view()?.slice();
return (
<div
id="graph-wrapper"
@@ -927,7 +846,6 @@ class Graph extends React.Component<{}, GraphState> {
}}
>
<GraphOverlayLayer
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element; width: any; height: any... Remove this comment to see the full error message
width={viewport.width}
height={viewport.height}
cameraTF={cameraTF}
@@ -987,7 +905,6 @@ class Graph extends React.Component<{}, GraphState> {
}}
>
<Async.Pending initial>
{/* eslint-disable-next-line @typescript-eslint/no-use-before-define --- StillLoading used before defined */}
<StillLoading
displayName={layoutChoice.current}
width={viewport.width}
@@ -996,7 +913,6 @@ class Graph extends React.Component<{}, GraphState> {
</Async.Pending>
<Async.Rejected>
{(error) => (
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- ErrorLoading used before defined
<ErrorLoading
displayName={layoutChoice.current}
error={error}
@@ -1019,8 +935,7 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const ErrorLoading = ({ displayName, error, width, height }: any) => {
const ErrorLoading = ({ displayName, error, width, height }) => {
console.log(error); // log to console as this is an unepected error
return (
<div
@@ -1036,30 +951,32 @@ const ErrorLoading = ({ displayName, error, width, height }: any) => {
);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const StillLoading = ({ displayName, width, height }: any) => (
const StillLoading = ({ displayName, width, height }) =>
/*
Render a busy/loading indicator
*/
<div
style={{
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
}}
>
(
<div
style={{
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
}}
>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
<div
style={{
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
}}
>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
</div>
</div>
</div>
);
)
;
export default Graph;
@@ -0,0 +1,218 @@
import React, { PureComponent } from "react";
import { connect, shallowEqual } from "react-redux";
import Async from "react-async";
import { categoryLabelDisplayStringLongLength } from "../../../globals";
import calcCentroid from "../../../util/centroid";
import { createColorQuery } from "../../../util/stateManager/colorHelpers";
export default
@connect((state) => ({
annoMatrix: state.annoMatrix,
colors: state.colors,
layoutChoice: state.layoutChoice,
dilatedValue: state.pointDilation.categoryField,
categoricalSelection: state.categoricalSelection,
showLabels: state.centroidLabels?.showLabels,
genesets: state.genesets.genesets,
}))
class CentroidLabels extends PureComponent {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
fetchAsyncProps = async (props) => {
const {
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
showLabels,
} = props.watchProps;
const { schema } = annoMatrix;
const { colorAccessor } = colors;
const [layoutDf, colorDf] = await this.fetchData();
let labels;
if (colorDf) {
labels = calcCentroid(
schema,
colorAccessor,
colorDf,
layoutChoice,
layoutDf
);
} else {
labels = new Map();
}
const { overlaySetShowing } = this.props;
overlaySetShowing("centroidLabels", showLabels && labels.size > 0);
return {
labels,
colorAccessor,
category: categoricalSelection[colorAccessor],
};
};
handleMouseEnter = (e, colorAccessor, label) => {
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover start",
metadataField: colorAccessor,
categoryField: label,
});
};
handleMouseOut = (e, colorAccessor, label) => {
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover end",
metadataField: colorAccessor,
categoryField: label,
});
};
colorByQuery() {
const { annoMatrix, colors, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
async fetchData() {
const { annoMatrix, layoutChoice } = this.props;
// fetch all data we need: layout, category
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// category to label - we ONLY label on obs, never on X, etc.
const query = this.colorByQuery();
if (query && query[0] === "obs") {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
render() {
const {
inverseTransform,
dilatedValue,
categoricalSelection,
showLabels,
colors,
annoMatrix,
layoutChoice,
} = this.props;
return (
<Async
watchFn={CentroidLabels.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
dilatedValue,
showLabels,
}}
>
<Async.Fulfilled>
{(asyncProps) => {
if (!showLabels) return null;
const labelSVGS = [];
const deselectOpacity = 0.375;
const { category, colorAccessor, labels } = asyncProps;
labels.forEach((coords, label) => {
const selected = category.get(label) ?? true;
// Mirror LSB middle truncation
let displayLabel = label;
if (displayLabel.length > categoryLabelDisplayStringLongLength) {
displayLabel = `${label.slice(
0,
categoryLabelDisplayStringLongLength / 2
)}${label.slice(-categoryLabelDisplayStringLongLength / 2)}`;
}
labelSVGS.push(
// eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative
<Label
key={label} // eslint-disable-line react/no-array-index-key --- label is not an index, eslint is confused
label={label}
dilatedValue={dilatedValue}
coords={coords}
inverseTransform={inverseTransform}
opactity={selected ? 1 : deselectOpacity}
colorAccessor={colorAccessor}
displayLabel={displayLabel}
onMouseEnter={this.handleMouseEnter}
onMouseOut={this.handleMouseOut}
/>
);
});
return <>{labelSVGS}</>;
}}
</Async.Fulfilled>
</Async>
);
}
}
const Label = ({
label,
dilatedValue,
coords,
inverseTransform,
opacity,
colorAccessor,
displayLabel,
onMouseEnter,
onMouseOut,
}) => {
/*
Render a label at a given coordinate.
*/
let fontSize = "15px";
let fontWeight = null;
if (label === dilatedValue) {
fontSize = "18px";
fontWeight = "800";
}
return (
<g
key={label}
className="centroid-label"
transform={`translate(${coords[0]}, ${coords[1]})`}
data-testclass="centroid-label"
data-testid={`${label}-centroid-label`}
>
{/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/}
<text
transform={inverseTransform}
textAnchor="middle"
style={{
fontSize,
fontWeight,
fill: "black",
userSelect: "none",
opacity: { opacity },
}}
onMouseEnter={(e) => onMouseEnter(e, colorAccessor, label)}
onMouseOut={(e) => onMouseOut(e, colorAccessor, label)}
pointerEvents="visiblePainted"
>
{displayLabel}
</text>
</g>
);
};
@@ -1,241 +0,0 @@
import React, { PureComponent } from "react";
import { connect, shallowEqual } from "react-redux";
import Async from "react-async";
import { categoryLabelDisplayStringLongLength } from "../../../globals";
import calcCentroid from "../../../util/centroid";
import { createColorQuery } from "../../../util/stateManager/colorHelpers";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
layoutChoice: (state as any).layoutChoice,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
dilatedValue: (state as any).pointDilation.categoryField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
categoricalSelection: (state as any).categoricalSelection,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
showLabels: (state as any).centroidLabels?.showLabels,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
}))
export default class CentroidLabels extends PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
const {
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
showLabels,
} = props.watchProps;
const { schema } = annoMatrix;
const { colorAccessor } = colors;
const [layoutDf, colorDf] = await this.fetchData();
let labels;
if (colorDf) {
labels = calcCentroid(
schema,
colorAccessor,
colorDf,
layoutChoice,
layoutDf
);
} else {
labels = new Map();
}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'overlaySetShowing' does not exist on typ... Remove this comment to see the full error message
const { overlaySetShowing } = this.props;
overlaySetShowing("centroidLabels", showLabels && labels.size > 0);
return {
labels,
colorAccessor,
category: categoricalSelection[colorAccessor],
};
};
// @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleMouseEnter = (e: any, colorAccessor: any, label: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover start",
metadataField: colorAccessor,
categoryField: label,
});
};
// @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleMouseOut = (e: any, colorAccessor: any, label: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover end",
metadataField: colorAccessor,
categoryField: label,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
colorByQuery() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, colors, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async fetchData() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, layoutChoice } = this.props;
// fetch all data we need: layout, category
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// category to label - we ONLY label on obs, never on X, etc.
const query = this.colorByQuery();
if (query && query[0] === "obs") {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'inverseTransform' does not exist on type... Remove this comment to see the full error message
inverseTransform,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dilatedValue' does not exist on type 'Re... Remove this comment to see the full error message
dilatedValue,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
categoricalSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'showLabels' does not exist on type 'Read... Remove this comment to see the full error message
showLabels,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on type 'Re... Remove this comment to see the full error message
layoutChoice,
} = this.props;
return (
<Async
watchFn={CentroidLabels.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
dilatedValue,
showLabels,
}}
>
<Async.Fulfilled>
{(asyncProps) => {
if (!showLabels) return null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const labelSVGS: any = [];
const deselectOpacity = 0.375;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'category' does not exist on type 'unknow... Remove this comment to see the full error message
const { category, colorAccessor, labels } = asyncProps;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
labels.forEach((coords: any, label: any) => {
const selected = category.get(label) ?? true;
// Mirror LSB middle truncation
let displayLabel = label;
if (displayLabel.length > categoryLabelDisplayStringLongLength) {
displayLabel = `${label.slice(
0,
categoryLabelDisplayStringLongLength / 2
)}${label.slice(-categoryLabelDisplayStringLongLength / 2)}`;
}
labelSVGS.push(
// eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative
<Label
key={label} // eslint-disable-line react/no-array-index-key --- label is not an index, eslint is confused
label={label}
dilatedValue={dilatedValue}
coords={coords}
inverseTransform={inverseTransform}
opactity={selected ? 1 : deselectOpacity}
colorAccessor={colorAccessor}
displayLabel={displayLabel}
onMouseEnter={this.handleMouseEnter}
onMouseOut={this.handleMouseOut}
/>
);
});
return <>{labelSVGS}</>;
}}
</Async.Fulfilled>
</Async>
);
}
}
const Label = ({
label,
dilatedValue,
coords,
inverseTransform,
opacity,
colorAccessor,
displayLabel,
onMouseEnter,
onMouseOut, // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
}: any) => {
/*
Render a label at a given coordinate.
*/
let fontSize = "15px";
let fontWeight = null;
if (label === dilatedValue) {
fontSize = "18px";
fontWeight = "800";
}
return (
<g
key={label}
className="centroid-label"
transform={`translate(${coords[0]}, ${coords[1]})`}
data-testclass="centroid-label"
data-testid={`${label}-centroid-label`}
>
{/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/}
<text
transform={inverseTransform}
textAnchor="middle"
style={{
fontSize,
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string | null' is not assignable to type 'Fo... Remove this comment to see the full error message
fontWeight,
fill: "black",
userSelect: "none",
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ opacity: any; }' is not assignable to type... Remove this comment to see the full error message
opacity: { opacity },
}}
onMouseEnter={(e) => onMouseEnter(e, colorAccessor, label)}
onMouseOut={(e) => onMouseOut(e, colorAccessor, label)}
pointerEvents="visiblePainted"
>
{displayLabel}
</text>
</g>
);
};
@@ -1,29 +1,22 @@
import React, { PureComponent, cloneElement } from "react";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module '../graph.css' or its correspon... Remove this comment to see the full error message
import styles from "../graph.css";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
export default class GraphOverlayLayer extends PureComponent<{}, State> {
export default class GraphOverlayLayer extends PureComponent {
/*
This component takes its children (assumed in the data coordinate space ([0, 1] range, origin in bottom left corner))
and transforms itself multiple times resulting in screen space ([0, screenWidth/Height] range, origin in top left corner)
Children are assigned in the graph component and must implement onDisplayChange()
*/
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
this.state = {
display: {},
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
matrixToTransformString = (m: any) =>
matrixToTransformString = (m) =>
/*
Translates the gl-matrix mat3 to SVG matrix transform style
@@ -32,37 +25,24 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> {
b d f / [a, b, 0, c, d, 0, e, f, 1] => matrix(a, b, c, d, e, f) / matrix(sx, 0, 0, sy, tx, ty) / matrix(m[0] m[3] m[1] m[4] m[6] m[7])
0 0 1
*/
`matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`;
`matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`
;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
reverseMatrixScaleTransformString = (m: any) =>
`matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`;
reverseMatrixScaleTransformString = (m) => `matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`;
// This is passed to all children, should be called when an overlay's display state is toggled along with the overlay name and its new display state in boolean form
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
overlaySetShowing = (overlay: any, displaying: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({
...state,
display: { ...state.display, [overlay]: displaying },
}));
overlaySetShowing = (overlay, displaying) => {
this.setState((state) => ({ ...state, display: { ...state.display, [overlay]: displaying } }));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cameraTF' does not exist on type 'Readon... Remove this comment to see the full error message
cameraTF,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'modelTF' does not exist on type 'Readonl... Remove this comment to see the full error message
modelTF,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'projectionTF' does not exist on type 'Re... Remove this comment to see the full error message
projectionTF,
children,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCanvasEvent' does not exist on typ... Remove this comment to see the full error message
handleCanvasEvent,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
width,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message
height,
} = this.props;
const { display } = this.state;
@@ -81,7 +61,6 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> {
// Copy the children passed with the overlay and add the inverse transform and onDisplayChange props
const newChildren = React.Children.map(children, (child) =>
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
cloneElement(child, {
inverseTransform,
overlaySetShowing: this.overlaySetShowing,
@@ -1,28 +1,19 @@
import * as d3 from "d3";
import { Colors } from "@blueprintjs/core";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
const Lasso = () => {
const dispatch = d3.dispatch("start", "end", "cancel");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const lasso = (svg: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoPolygon: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoPath: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let closePath: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoInProgress: any;
const lasso = (svg) => {
let lassoPolygon;
let lassoPath;
let closePath;
let lassoInProgress;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const polygonToPath = (polygon: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
`M${polygon.map((d: any) => d.join(",")).join("L")}`;
const polygonToPath = (polygon) =>
`M${polygon.map((d) => d.join(",")).join("L")}`;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const distance = (pt1: any, pt2: any) =>
const distance = (pt1, pt2) =>
Math.sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2);
// distance last point has to be to first point before it auto closes when mouse is released
@@ -30,14 +21,12 @@ const Lasso = () => {
const lassoPathColor = Colors.BLUE5;
const handleDragStart = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lassoPolygon = [(d3 as any).mouse(svg.node())]; // current x y of mouse within element
lassoPolygon = [d3.mouse(svg.node())]; // current x y of mouse within element
if (lassoPath) {
// If the existing path is in progress
if (lassoInProgress) {
// cancel the existing lasso
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- handleCancel used before defined
handleCancel();
// Don't continue with current drag start
return;
@@ -48,14 +37,12 @@ const Lasso = () => {
// We're starting a new drag
lassoInProgress = true;
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined
lassoPath = g
.append("path")
.attr("data-testid", "lasso-element")
.attr("fill-opacity", 0.1)
.attr("stroke-dasharray", "3, 3");
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined
closePath = g
.append("line")
.attr("x2", lassoPolygon[0][0])
@@ -66,8 +53,7 @@ const Lasso = () => {
};
const handleDrag = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const point = (d3 as any).mouse(svg.node());
const point = d3.mouse(svg.node());
lassoPolygon.push(point);
lassoPath.attr("d", polygonToPath(lassoPolygon));
@@ -137,12 +123,12 @@ const Lasso = () => {
area.call(drag);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(lasso as any).reset = () => {
lasso.reset = () => {
if (lassoPath) {
lassoPath.remove();
lassoPath = null;
}
lassoPolygon = null;
if (closePath) {
closePath.remove();
@@ -150,11 +136,10 @@ const Lasso = () => {
}
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(lasso as any).move = (polygon: any) => {
lasso.move = (polygon) => {
if (polygon !== lassoPolygon || polygon.length !== lassoPolygon.length) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'reset' does not exist on type '(svg: any... Remove this comment to see the full error message
lasso.reset();
lassoPolygon = polygon;
lassoPath = g
.append("path")
@@ -163,13 +148,13 @@ const Lasso = () => {
.attr("fill-opacity", 0.1)
.attr("stroke", lassoPathColor)
.attr("stroke-dasharray", "3, 3");
lassoPath.attr("d", `${polygonToPath(lassoPolygon)}Z`);
}
};
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lasso.on = (type: any, callback: any) => {
lasso.on = (type, callback) => {
dispatch.on(type, callback);
return lasso;
};
@@ -0,0 +1,54 @@
import * as d3 from "d3";
import Lasso from "./setupLasso";
/******************************************
*******************************************
put svg & brush in DOM
*******************************************
******************************************/
export default (
selectionToolType,
handleStartAction,
handleDragAction,
handleEndAction,
handleCancelAction,
viewport
) => {
const svg = d3.select("#graph-wrapper").select("#lasso-layer");
if (svg.empty()) return {};
if (selectionToolType === "brush") {
const brush = d3
.brush()
.extent([
[0, 0],
[viewport.width, viewport.height],
])
.on("start", handleStartAction)
.on("brush", handleDragAction)
// FYI, brush doesn't generate cancel
.on("end", handleEndAction);
const brushContainer = svg
.append("g")
.attr("class", "graph_brush")
.call(brush);
return { svg, container: brushContainer, tool: brush };
}
if (selectionToolType === "lasso") {
const lasso = Lasso()
.on("end", handleEndAction)
// FYI, Lasso doesn't generate drag
.on("start", handleStartAction)
.on("cancel", handleCancelAction);
const lassoContainer = svg.call(lasso);
return { svg, container: lassoContainer, tool: lasso };
}
throw new Error("unknown graph selection tool");
};
@@ -1,62 +0,0 @@
import * as d3 from "d3";
import Lasso from "./setupLasso";
/******************************************
*******************************************
put svg & brush in DOM
*******************************************
******************************************/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export default (
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
selectionToolType: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleStartAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleDragAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleEndAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCancelAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
viewport: any
) => {
const svg = d3.select("#graph-wrapper").select("#lasso-layer");
if (svg.empty()) return {};
if (selectionToolType === "brush") {
const brush = d3
.brush()
.extent([
[0, 0],
[viewport.width, viewport.height],
])
.on("start", handleStartAction)
.on("brush", handleDragAction)
// FYI, brush doesn't generate cancel
.on("end", handleEndAction);
const brushContainer = svg
.append("g")
.attr("class", "graph_brush")
.call(brush);
return { svg, container: brushContainer, tool: brush };
}
if (selectionToolType === "lasso") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const lasso = (Lasso() as any)
.on("end", handleEndAction)
// FYI, Lasso doesn't generate drag
.on("start", handleStartAction)
.on("cancel", handleCancelAction);
const lassoContainer = svg.call(lasso);
return { svg, container: lassoContainer, tool: lasso };
}
throw new Error("unknown graph selection tool");
};
@@ -0,0 +1,61 @@
import React, { PureComponent } from "react";
import { connect } from "react-redux";
import { Drawer } from "@blueprintjs/core";
import InfoFormat from "./infoFormat";
import { selectableCategoryNames } from "../../util/stateManager/controlsHelpers";
@connect((state) => ({
schema: state.annoMatrix.schema,
datasetTitle: state.config?.displayNames?.dataset ?? "",
aboutURL: state.config?.links?.["about-dataset"],
isOpen: state.controls.datasetDrawer,
dataPortalProps: state.config?.corpora_props,
}))
class InfoDrawer extends PureComponent {
handleClose = () => {
const { dispatch } = this.props;
dispatch({ type: "toggle dataset drawer" });
};
render() {
const {
position,
aboutURL,
datasetTitle,
schema,
isOpen,
dataPortalProps,
} = this.props;
const allCategoryNames = selectableCategoryNames(schema).sort();
const singleValueCategories = new Map();
allCategoryNames.forEach((catName) => {
const isUserAnno = schema?.annotations?.obsByName[catName]?.writable;
const colSchema = schema.annotations.obsByName[catName];
if (!isUserAnno && colSchema.categories?.length === 1) {
singleValueCategories.set(catName, colSchema.categories[0]);
}
});
return (
<Drawer
title="Dataset Overview"
onClose={this.handleClose}
{...{ isOpen, position }}
>
<InfoFormat
{...{
datasetTitle,
aboutURL,
singleValueCategories,
dataPortalProps: dataPortalProps ?? {},
}}
/>
</Drawer>
);
}
}
export default InfoDrawer;
@@ -1,78 +0,0 @@
import React, { PureComponent } from "react";
import { connect } from "react-redux";
import { Drawer } from "@blueprintjs/core";
import InfoFormat from "./infoFormat";
import { selectableCategoryNames } from "../../util/stateManager/controlsHelpers";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema: (state as any).annoMatrix.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
datasetTitle: (state as any).config?.displayNames?.dataset ?? "",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
aboutURL: (state as any).config?.links?.["about-dataset"],
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
isOpen: (state as any).controls.datasetDrawer,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
dataPortalProps: (state as any).config?.corpora_props,
}))
class InfoDrawer extends PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleClose = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({ type: "toggle dataset drawer" });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'position' does not exist on type 'Readon... Remove this comment to see the full error message
position,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'aboutURL' does not exist on type 'Readon... Remove this comment to see the full error message
aboutURL,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type 'Re... Remove this comment to see the full error message
datasetTitle,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
schema,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
isOpen,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dataPortalProps' does not exist on type ... Remove this comment to see the full error message
dataPortalProps,
} = this.props;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const allCategoryNames = selectableCategoryNames(schema).sort();
const singleValueCategories = new Map();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
allCategoryNames.forEach((catName: any) => {
const isUserAnno = schema?.annotations?.obsByName[catName]?.writable;
const colSchema = schema.annotations.obsByName[catName];
if (!isUserAnno && colSchema.categories?.length === 1) {
singleValueCategories.set(catName, colSchema.categories[0]);
}
});
return (
<Drawer
title="Dataset Overview"
onClose={this.handleClose}
{...{ isOpen, position }}
>
<InfoFormat
{...{
datasetTitle,
aboutURL,
singleValueCategories,
dataPortalProps: dataPortalProps ?? {},
}}
/>
</Drawer>
);
}
}
export default InfoDrawer;
@@ -1,16 +1,14 @@
import { H3, H1, UL, HTMLTable, Classes } from "@blueprintjs/core";
import React from "react";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const renderContributors = (contributors: any, affiliations: any) => {
const renderContributors = (contributors, affiliations) => {
// eslint-disable-next-line no-constant-condition -- Temp removed contributor section to avoid publishing PII
if (!contributors || contributors.length === 0 || true) return null;
return (
<>
<H3>Contributors</H3>
<p>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{contributors.map((contributor: any) => {
{contributors.map((contributor) => {
const { email, name, institution } = contributor;
return (
@@ -29,8 +27,7 @@ const renderContributors = (contributors: any, affiliations: any) => {
// generates a list of unique institutions by order of appearance in contributors
const buildAffiliations = (contributors = []) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const affiliations: any = [];
const affiliations = [];
contributors.forEach((contributor) => {
const { institution } = contributor;
if (affiliations.indexOf(institution) === -1) {
@@ -40,15 +37,13 @@ const buildAffiliations = (contributors = []) => {
return affiliations;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const renderAffiliations = (affiliations: any) => {
const renderAffiliations = (affiliations) => {
if (affiliations.length === 0) return null;
return (
<>
<H3>Affiliations</H3>
<UL>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{affiliations.map((item: any, index: any) => (
{affiliations.map((item, index) => (
<div key={item}>
<sup>{index + 1}</sup>
{" "}
@@ -60,8 +55,7 @@ const renderAffiliations = (affiliations: any) => {
);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const renderDOILink = (type: any, doi: any) => {
const renderDOILink = (type, doi) => {
if (!doi) return null;
return (
<>
@@ -77,12 +71,7 @@ const renderDOILink = (type: any, doi: any) => {
const ONTOLOGY_KEY = "ontology_term_id";
// Render list of metadata attributes found in categorical field
const renderDatasetMetadata = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
singleValueCategories: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
corporaMetadata: any
) => {
const renderDatasetMetadata = (singleValueCategories, corporaMetadata) => {
if (singleValueCategories.size === 0) return null;
return (
<>
@@ -101,34 +90,29 @@ const renderDatasetMetadata = (
</thead>
<tbody>
{Object.entries(corporaMetadata).map(([key, value]) => (
<tr {...{ key }}>
<td>{`${key}:`}</td>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'ReactNod... Remove this comment to see the full error message */}
<td>{value}</td>
<td />
</tr>
))}
<tr {...{ key }}>
<td>{`${key}:`}</td>
<td>{value}</td>
<td />
</tr>
))}
{Array.from(singleValueCategories).reduce((elems, pair) => {
// @ts-expect-error ts-migrate(2488) FIXME: Type 'unknown' must have a '[Symbol.iterator]()' m... Remove this comment to see the full error message
const [category, value] = pair;
// If the value is empty skip it
if (!value) return elems;
// If this category is a ontology term, let's add its value to the previous node
if (String(category).includes(ONTOLOGY_KEY)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const prevElem = (elems as any).pop();
const prevElem = elems.pop();
const newChildren = [...prevElem.props.children];
newChildren.splice(2, 1, [<td key="ontology">{value}</td>]);
// Props aren't extensible so we must clone and alter the component to append the new child
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(elems as any).push(
elems.push(
React.cloneElement(prevElem, prevElem.props, newChildren)
);
} else {
// Create the list item
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(elems as any).push(
elems.push(
<tr key={category}>
<td>{`${category}:`}</td>
<td>{value}</td>
@@ -146,16 +130,14 @@ const renderDatasetMetadata = (
// Renders any links found in the config where link_type is not "SUMMARY"
// If there are no links in the config, render the aboutURL
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const renderLinks = (projectLinks: any, aboutURL: any) => {
const renderLinks = (projectLinks, aboutURL) => {
if (!projectLinks && !aboutURL) return null;
if (projectLinks)
return (
<>
<H3>Project Links</H3>
<UL>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */}
{projectLinks.map((link: any) => {
{projectLinks.map((link) => {
if (link.link_type === "SUMMARY") return null;
return (
<li key={link.link_name}>
@@ -182,7 +164,6 @@ const renderLinks = (projectLinks: any, aboutURL: any) => {
};
const InfoFormat = React.memo(
// @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type '{ ... Remove this comment to see the full error message
({ datasetTitle, singleValueCategories, aboutURL, dataPortalProps = {} }) => {
if (
["1.0.0", "1.1.0"].indexOf(
@@ -3,11 +3,7 @@ import { InputGroup, MenuItem, Keys } from "@blueprintjs/core";
import { Suggest } from "@blueprintjs/select";
import fuzzysort from "fuzzysort";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
export default class LabelInput extends React.PureComponent<{}, State> {
export default class LabelInput extends React.PureComponent {
/*
Input widget for text labels, which acts like an InputGroup, but will also
accept a suggestion list (of labels), with sublime-like suggest search.
@@ -30,11 +26,9 @@ export default class LabelInput extends React.PureComponent<{}, State> {
/* maxinum number of suggestions */
static QueryResultLimit = 100;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type '{}'.
const { label } = props;
const query = label || "";
const queryResults = this.filterLabels(query);
@@ -44,8 +38,7 @@ export default class LabelInput extends React.PureComponent<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleQueryChange = (query: any, event: any) => {
handleQueryChange = (query, event) => {
// https://github.com/palantir/blueprint/issues/2983
if (!event) return;
@@ -55,23 +48,19 @@ export default class LabelInput extends React.PureComponent<{}, State> {
queryResults,
});
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onChange' does not exist on type 'Readon... Remove this comment to see the full error message
const { onChange } = this.props;
if (onChange) onChange(query, event);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleItemSelect = (item: any, event: any) => {
handleItemSelect = (item, event) => {
/* only report the select if not already reported via onChange() */
const { target } = item;
const { query } = this.state;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onSelect' does not exist on type 'Readon... Remove this comment to see the full error message
const { onSelect } = this.props;
if (target !== query && onSelect) onSelect(target, event);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleKeyDown = (e: any) => {
handleKeyDown = (e) => {
/*
prevent these events from propagating to containing form/dialog
and causing further side effects (eg, closing dialog, submitting
@@ -86,22 +75,13 @@ export default class LabelInput extends React.PureComponent<{}, State> {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleChange = (e: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onChange' does not exist on type 'Readon... Remove this comment to see the full error message
handleChange = (e) => {
const { onChange } = this.props;
if (onChange) onChange(e.target.value);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderLabelSuggestion = (
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
queryResult: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
{ handleClick, modifiers }: any
) => {
renderLabelSuggestion = (queryResult, { handleClick, modifiers }) => {
if (queryResult.newLabel) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'newLabelMessage' does not exist on type ... Remove this comment to see the full error message
const { newLabelMessage } = this.props;
return (
<MenuItem
@@ -126,23 +106,18 @@ export default class LabelInput extends React.PureComponent<{}, State> {
);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
filterLabels(query: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'labelSuggestions' does not exist on type... Remove this comment to see the full error message
filterLabels(query) {
const { labelSuggestions } = this.props;
if (!labelSuggestions) return [];
/* empty query is wildcard */
if (query === "") {
return (
labelSuggestions
.slice(0, LabelInput.QueryResultLimit)
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.map((l: any) => ({
target: l,
score: -10000,
}))
);
return labelSuggestions
.slice(0, LabelInput.QueryResultLimit)
.map((l) => ({
target: l,
score: -10000,
}));
}
/* else, do a fuzzy query */
@@ -153,16 +128,13 @@ export default class LabelInput extends React.PureComponent<{}, State> {
let queryResults = fuzzysort.go(query, labelSuggestions, options);
/* exact match will always be first in list */
if (query !== "" && queryResults[0]?.target !== query)
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ target: any; newLabel: true; }' is not ass... Remove this comment to see the full error message
queryResults = [{ target: query, newLabel: true }, ...queryResults];
return queryResults;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { props } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'labelSuggestions' does not exist on type... Remove this comment to see the full error message
const { labelSuggestions, label, autoFocus = true } = props;
const suggestEnabled = !!labelSuggestions && labelSuggestions.length > 0;
@@ -170,8 +142,7 @@ export default class LabelInput extends React.PureComponent<{}, State> {
return (
<InputGroup
autoFocus={autoFocus}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
{...(props as any).inputProps} // eslint-disable-line react/jsx-props-no-spreading --- Allows for modularity
{...props.inputProps} // eslint-disable-line react/jsx-props-no-spreading --- Allows for modularity
value={label}
onChange={this.handleChange}
/>
@@ -180,12 +151,10 @@ export default class LabelInput extends React.PureComponent<{}, State> {
const popoverProps = {
minimal: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
...(props as any).popoverProps,
...props.popoverProps,
};
const inputProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
...(props as any).inputProps,
...props.inputProps,
autoFocus: false,
};
const { queryResults } = this.state;
@@ -201,7 +170,6 @@ export default class LabelInput extends React.PureComponent<{}, State> {
onQueryChange={this.handleQueryChange}
popoverProps={popoverProps}
inputProps={inputProps}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ fill: true; inputValueRenderer: (i: any) =... Remove this comment to see the full error message
onKeyDown={this.handleKeyDown}
/>
</>
@@ -6,17 +6,12 @@ import DynamicScatterplot from "../scatterplot/scatterplot";
import TopLeftLogoAndTitle from "./topLeftLogoAndTitle";
import Continuous from "../continuous/continuous";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor,
scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
}))
class LeftSideBar extends React.Component {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message
const { scatterplotXXaccessor, scatterplotYYaccessor } = this.props;
return (
<div
@@ -3,7 +3,6 @@ import { Button, Menu, MenuItem, Popover, Position } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
const InformationMenu = React.memo((props) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'libraryVersions' does not exist on type ... Remove this comment to see the full error message
const { libraryVersions, tosURL, privacyURL } = props;
return (
<Popover
@@ -0,0 +1,116 @@
import React from "react";
import { connect } from "react-redux";
import { Button } from "@blueprintjs/core";
import * as globals from "../../globals";
import Logo from "../framework/logo";
import Truncate from "../util/truncate";
import InfoDrawer from "../infoDrawer/infoDrawer";
import InformationMenu from "./infoMenu";
const DATASET_TITLE_FONT_SIZE = 14;
@connect((state) => {
const { corpora_props: corporaProps } = state.config;
const correctVersion =
["1.0.0", "1.1.0"].indexOf(corporaProps?.version?.corpora_schema_version) >
-1;
return {
datasetTitle: state.config?.displayNames?.dataset ?? "",
libraryVersions: state.config?.library_versions,
aboutLink: state.config?.links?.["about-dataset"],
tosURL: state.config?.parameters?.about_legal_tos,
privacyURL: state.config?.parameters?.about_legal_privacy,
title: correctVersion ? corporaProps?.title : undefined,
};
})
class LeftSideBar extends React.Component {
handleClick = () => {
const { dispatch } = this.props;
dispatch({ type: "toggle dataset drawer" });
};
render() {
const {
datasetTitle,
libraryVersions,
aboutLink,
privacyURL,
tosURL,
dispatch,
title,
} = this.props;
return (
<div
style={{
paddingLeft: 8,
paddingTop: 8,
width: globals.leftSidebarWidth,
zIndex: 1,
borderBottom: `1px solid ${globals.lighterGrey}`,
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>
<Logo size={28} />
<span
style={{
fontSize: 24,
position: "relative",
top: -6,
fontWeight: "bold",
marginLeft: 5,
color: globals.logoColor,
userSelect: "none",
}}
>
cell
<span
style={{
position: "relative",
top: 1,
fontWeight: 300,
fontSize: 24,
}}
>
×
</span>
gene
</span>
</div>
<div style={{ marginRight: 5, height: "100%" }}>
<Button
minimal
style={{
fontSize: DATASET_TITLE_FONT_SIZE,
position: "relative",
top: -1,
}}
onClick={this.handleClick}
>
<Truncate>
<span style={{ maxWidth: 155 }} data-testid="header">
{title ?? datasetTitle}
</span>
</Truncate>
</Button>
<InfoDrawer />
<InformationMenu
{...{
libraryVersions,
aboutLink,
tosURL,
privacyURL,
dispatch,
}}
/>
</div>
</div>
);
}
}
export default LeftSideBar;
@@ -1,133 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import { Button } from "@blueprintjs/core";
import * as globals from "../../globals";
import Logo from "../framework/logo";
import Truncate from "../util/truncate";
import InfoDrawer from "../infoDrawer/infoDrawer";
import InformationMenu from "./infoMenu";
const DATASET_TITLE_FONT_SIZE = 14;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const { corpora_props: corporaProps } = (state as any).config;
const correctVersion =
["1.0.0", "1.1.0"].indexOf(corporaProps?.version?.corpora_schema_version) >
-1;
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
datasetTitle: (state as any).config?.displayNames?.dataset ?? "",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
libraryVersions: (state as any).config?.library_versions,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
aboutLink: (state as any).config?.links?.["about-dataset"],
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
tosURL: (state as any).config?.parameters?.about_legal_tos,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
privacyURL: (state as any).config?.parameters?.about_legal_privacy,
title: correctVersion ? corporaProps?.title : undefined,
};
})
class LeftSideBar extends React.Component {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleClick = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({ type: "toggle dataset drawer" });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type 'Re... Remove this comment to see the full error message
datasetTitle,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'libraryVersions' does not exist on type ... Remove this comment to see the full error message
libraryVersions,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'aboutLink' does not exist on type 'Reado... Remove this comment to see the full error message
aboutLink,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'privacyURL' does not exist on type 'Read... Remove this comment to see the full error message
privacyURL,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message
tosURL,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'title' does not exist on type 'Readonly<... Remove this comment to see the full error message
title,
} = this.props;
return (
<div
style={{
paddingLeft: 8,
paddingTop: 8,
width: globals.leftSidebarWidth,
zIndex: 1,
borderBottom: `1px solid ${globals.lighterGrey}`,
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>
<Logo size={28} />
<span
style={{
fontSize: 24,
position: "relative",
top: -6,
fontWeight: "bold",
marginLeft: 5,
color: globals.logoColor,
userSelect: "none",
}}
>
cell
<span
style={{
position: "relative",
top: 1,
fontWeight: 300,
fontSize: 24,
}}
>
×
</span>
gene
</span>
</div>
<div style={{ marginRight: 5, height: "100%" }}>
<Button
minimal
style={{
fontSize: DATASET_TITLE_FONT_SIZE,
position: "relative",
top: -1,
}}
onClick={this.handleClick}
>
<Truncate>
<span style={{ maxWidth: 155 }} data-testid="header">
{title ?? datasetTitle}
</span>
</Truncate>
</Button>
<InfoDrawer />
<InformationMenu
{...{
libraryVersions,
aboutLink,
tosURL,
privacyURL,
dispatch,
}}
/>
</div>
</div>
);
}
}
export default LeftSideBar;
@@ -17,7 +17,6 @@ import { IconNames } from "@blueprintjs/icons";
import * as globals from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
import { storageGet, storageSet, KEYS } from "../util/localStorage";
@@ -32,13 +31,11 @@ const LOGIN_PROMPT_OFF = "off";
const Auth = React.memo((props) => {
const [isPromptOpen, setIsPromptOpen] = useState(shouldShowPrompt());
// @ts-expect-error ts-migrate(2339) FIXME: Property 'auth' does not exist on type '{ children... Remove this comment to see the full error message
const { auth, userInfo } = props;
const isAuthenticated = userInfo && userInfo.is_authenticated;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(window as any).userInfo = userInfo;
window.userInfo = userInfo;
const randomInt = Math.random() * 15;
const sexIndex = Math.floor(randomInt / 5);
@@ -78,7 +75,6 @@ const Auth = React.memo((props) => {
>
{/* eslint-disable-next-line no-constant-condition -- disable profile picture until CSP is tweaked */}
{userInfo?.picture && false ? (
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ alt: string; size: string; src: any; }' is... Remove this comment to see the full error message
<img alt="profile" size="21px" src={userInfo?.picture} />
) : (
<span style={{ fontSize: "18px" }}>{scientist}</span>
@@ -127,13 +123,11 @@ const Auth = React.memo((props) => {
function shouldShowPrompt() {
if (storageGet(KEYS.LOGIN_PROMPT) === LOGIN_PROMPT_OFF) return false;
// @ts-expect-error ts-migrate(2774) FIXME: This condition will always return true since the f... Remove this comment to see the full error message
return shouldShowAuth && !isAuthenticated;
}
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function PromptContent({ setIsPromptOpen }: any) {
function PromptContent({ setIsPromptOpen }) {
const [isChecked, setIsChecked] = useState(false);
function handleOKClick() {
@@ -4,22 +4,17 @@ import { connect } from "react-redux";
import { tooltipHoverOpenDelay } from "../../globals";
import actions from "../../actions";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
differential: (state as any).differential,
differential: state.differential,
}))
class CellSetButton extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
set() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, eitherCellSetOneOrTwo } = this.props;
dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'differential' does not exist on type 'Re... Remove this comment to see the full error message
const { differential, eitherCellSetOneOrTwo } = this.props;
const cellListName = `celllist${eitherCellSetOneOrTwo}`;
const cellsSelected = differential[cellListName]
@@ -12,30 +12,19 @@ import {
import { IconNames } from "@blueprintjs/icons";
import { tooltipHoverOpenDelay } from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
const Clip = React.memo((props) => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'pendingClipPercentiles' does not exist o... Remove this comment to see the full error message
pendingClipPercentiles,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message
clipPercentileMin,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message
clipPercentileMax,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipOpening' does not exist on typ... Remove this comment to see the full error message
handleClipOpening,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipClosing' does not exist on typ... Remove this comment to see the full error message
handleClipClosing,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipCommit' does not exist on type... Remove this comment to see the full error message
handleClipCommit,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isClipDisabled' does not exist on type '... Remove this comment to see the full error message
isClipDisabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipOnKeyPress' does not exist on ... Remove this comment to see the full error message
handleClipOnKeyPress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipPercentileMaxValueChange' does... Remove this comment to see the full error message
handleClipPercentileMaxValueChange,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipPercentileMinValueChange' does... Remove this comment to see the full error message
handleClipPercentileMinValueChange,
} = props;
@@ -45,8 +34,7 @@ const Clip = React.memo((props) => {
pendingClipPercentiles?.clipPercentileMax ?? clipPercentileMax;
const intent =
clipPercentileMin > 0 || clipPercentileMax < 100
? // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(Intent as any).INTENT_WARNING
? Intent.INTENT_WARNING
: Intent.NONE;
return (
@@ -2,25 +2,17 @@ import React from "react";
import { connect } from "react-redux";
import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
import * as globals from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
import actions from "../../actions";
import CellSetButton from "./cellSetButtons";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
differential: (state as any).differential,
diffexpMayBeSlow:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.["diffexp-may-be-slow"] ?? false,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
diffexpCellcountMax: (state as any).config?.limits?.diffexp_cellcount_max,
differential: state.differential,
diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false,
diffexpCellcountMax: state.config?.limits?.diffexp_cellcount_max,
}))
class DiffexpButtons extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
computeDiffExp = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, differential } = this.props;
if (differential.celllist1 && differential.celllist2) {
dispatch(
@@ -32,32 +24,33 @@ class DiffexpButtons extends React.PureComponent {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
/* diffexp-related buttons may be disabled */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'differential' does not exist on type 'Re... Remove this comment to see the full error message
const { differential, diffexpMayBeSlow, diffexpCellcountMax } = this.props;
const haveBothCellSets =
!!differential.celllist1 && !!differential.celllist2;
const haveEitherCellSet =
!!differential.celllist1 || !!differential.celllist2;
const slowMsg = diffexpMayBeSlow
? " (CAUTION: large dataset - may take longer or fail)"
: "";
const tipMessage = `See top 10 differentially expressed genes${slowMsg}`;
const tipMessageWarn = `The total number of cells for differential expression computation
may not exceed ${diffexpCellcountMax}. Try reselecting new cell sets.`;
const warnMaxSizeExceeded =
haveEitherCellSet &&
!!diffexpCellcountMax &&
(differential.celllist1?.length ?? 0) +
(differential.celllist2?.length ?? 0) >
diffexpCellcountMax;
return (
<ButtonGroup className={styles.menubarButton}>
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
<CellSetButton eitherCellSetOneOrTwo={1} />
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
<CellSetButton eitherCellSetOneOrTwo={2} />
<Tooltip
content={warnMaxSizeExceeded ? tipMessageWarn : tipMessage}
+327
View File
@@ -0,0 +1,327 @@
import React from "react";
import { connect } from "react-redux";
import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
import * as globals from "../../globals";
import styles from "./menubar.css";
import actions from "../../actions";
import Clip from "./clip";
import AuthButtons from "./authButtons";
import Subset from "./subset";
import UndoRedoReset from "./undoRedo";
import DiffexpButtons from "./diffexpButtons";
import { getEmbSubsetView } from "../../util/stateManager/viewStackHelpers";
@connect((state) => {
const { annoMatrix } = state;
const crossfilter = state.obsCrossfilter;
const selectedCount = crossfilter.countSelected();
const subsetPossible =
selectedCount !== 0 && selectedCount !== crossfilter.size(); // ie, not all and not none are selected
const embSubsetView = getEmbSubsetView(annoMatrix);
const subsetResetPossible = !embSubsetView
? annoMatrix.nObs !== annoMatrix.schema.dataframe.nObs
: annoMatrix.nObs !== embSubsetView.nObs;
return {
subsetPossible,
subsetResetPossible,
graphInteractionMode: state.controls.graphInteractionMode,
clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)),
clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)),
userDefinedGenes: state.controls.userDefinedGenes,
colorAccessor: state.colors.colorAccessor,
scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
libraryVersions: state.config?.library_versions,
auth: state.config?.authentication,
userInfo: state.userInfo,
undoDisabled: state["@@undoable/past"].length === 0,
redoDisabled: state["@@undoable/future"].length === 0,
aboutLink: state.config?.links?.["about-dataset"],
disableDiffexp: state.config?.parameters?.["disable-diffexp"] ?? false,
diffexpMayBeSlow:
state.config?.parameters?.["diffexp-may-be-slow"] ?? false,
showCentroidLabels: state.centroidLabels.showLabels,
tosURL: state.config?.parameters?.about_legal_tos,
privacyURL: state.config?.parameters?.about_legal_privacy,
categoricalSelection: state.categoricalSelection,
};
})
class MenuBar extends React.PureComponent {
static isValidDigitKeyEvent(e) {
/*
Return true if this event is necessary to enter a percent number input.
Return false if not.
Returns true for events with keys: backspace, control, alt, meta, [0-9],
or events that don't have a key.
*/
if (e.key === null) return true;
if (e.ctrlKey || e.altKey || e.metaKey) return true;
// concept borrowed from blueprint's numericInputUtils:
// keys that print a single character when pressed have a `key` name of
// length 1. every other key has a longer `key` name (e.g. "Backspace",
// "ArrowUp", "Shift"). since none of those keys can print a character
// to the field--and since they may have important native behaviors
// beyond printing a character--we don't want to disable their effects.
const isSingleCharKey = e.key.length === 1;
if (!isSingleCharKey) return true;
const key = e.key.charCodeAt(0) - 48; /* "0" */
return key >= 0 && key <= 9;
}
constructor(props) {
super(props);
this.state = {
pendingClipPercentiles: null,
};
}
isClipDisabled = () => {
/*
return true if clip button should be disabled.
*/
const { pendingClipPercentiles } = this.state;
const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin;
const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax;
const {
clipPercentileMin: currentClipMin,
clipPercentileMax: currentClipMax,
} = this.props;
// if you change this test, be careful with logic around
// comparisons between undefined / NaN handling.
const isDisabled =
!(clipPercentileMin < clipPercentileMax) ||
(clipPercentileMin === currentClipMin &&
clipPercentileMax === currentClipMax);
return isDisabled;
};
handleClipOnKeyPress = (e) => {
/*
allow only numbers, plus other critical keys which
may be required to make a number
*/
if (!MenuBar.isValidDigitKeyEvent(e)) {
e.preventDefault();
}
};
handleClipPercentileMinValueChange = (v) => {
/*
Ignore anything that isn't a legit number
*/
if (!Number.isFinite(v)) return;
const { pendingClipPercentiles } = this.state;
const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax;
/*
clamp to [0, currentClipPercentileMax]
*/
if (v <= 0) v = 0;
if (v > 100) v = 100;
const clipPercentileMin = Math.round(v); // paranoia
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
handleClipPercentileMaxValueChange = (v) => {
/*
Ignore anything that isn't a legit number
*/
if (!Number.isFinite(v)) return;
const { pendingClipPercentiles } = this.state;
const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin;
/*
clamp to [0, 100]
*/
if (v < 0) v = 0;
if (v > 100) v = 100;
const clipPercentileMax = Math.round(v); // paranoia
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
handleClipCommit = () => {
const { dispatch } = this.props;
const { pendingClipPercentiles } = this.state;
const { clipPercentileMin, clipPercentileMax } = pendingClipPercentiles;
const min = clipPercentileMin / 100;
const max = clipPercentileMax / 100;
dispatch(actions.clipAction(min, max));
};
handleClipOpening = () => {
const { clipPercentileMin, clipPercentileMax } = this.props;
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
handleClipClosing = () => {
this.setState({ pendingClipPercentiles: null });
};
handleCentroidChange = () => {
const { dispatch, showCentroidLabels } = this.props;
dispatch({
type: "show centroid labels for category",
showLabels: !showCentroidLabels,
});
};
handleSubset = () => {
const { dispatch } = this.props;
dispatch(actions.subsetAction());
};
handleSubsetReset = () => {
const { dispatch } = this.props;
dispatch(actions.resetSubsetAction());
};
render() {
const {
dispatch,
disableDiffexp,
undoDisabled,
redoDisabled,
selectionTool,
clipPercentileMin,
clipPercentileMax,
graphInteractionMode,
showCentroidLabels,
categoricalSelection,
colorAccessor,
subsetPossible,
subsetResetPossible,
userInfo,
auth,
} = this.props;
const { pendingClipPercentiles } = this.state;
const isColoredByCategorical = !!categoricalSelection?.[colorAccessor];
// constants used to create selection tool button
const [selectionTooltip, selectionButtonIcon] =
selectionTool === "brush"
? ["Brush selection", "Lasso selection"]
: ["select", "polygon-filter"];
return (
<div
style={{
position: "absolute",
right: 8,
top: 0,
display: "flex",
flexDirection: "row-reverse",
alignItems: "flex-start",
flexWrap: "wrap",
justifyContent: "flex-start",
zIndex: 3,
}}
>
<AuthButtons {...{ auth, userInfo }} />
<UndoRedoReset
dispatch={dispatch}
undoDisabled={undoDisabled}
redoDisabled={redoDisabled}
/>
<Clip
pendingClipPercentiles={pendingClipPercentiles}
clipPercentileMin={clipPercentileMin}
clipPercentileMax={clipPercentileMax}
handleClipOpening={this.handleClipOpening}
handleClipClosing={this.handleClipClosing}
handleClipCommit={this.handleClipCommit}
isClipDisabled={this.isClipDisabled}
handleClipOnKeyPress={this.handleClipOnKeyPress}
handleClipPercentileMaxValueChange={
this.handleClipPercentileMaxValueChange
}
handleClipPercentileMinValueChange={
this.handleClipPercentileMinValueChange
}
/>
<Tooltip
content="When a category is colored by, show labels on the graph"
position="bottom"
disabled={graphInteractionMode === "zoom"}
>
<AnchorButton
className={styles.menubarButton}
type="button"
data-testid="centroid-label-toggle"
icon="property"
onClick={this.handleCentroidChange}
active={showCentroidLabels}
intent={showCentroidLabels ? "primary" : "none"}
disabled={!isColoredByCategorical}
/>
</Tooltip>
<ButtonGroup className={styles.menubarButton}>
<Tooltip
content={selectionTooltip}
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-lasso"
icon={selectionButtonIcon}
active={graphInteractionMode === "select"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "select",
});
}}
/>
</Tooltip>
<Tooltip
content="Drag to pan, scroll to zoom"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-pan-zoom"
icon="zoom-in"
active={graphInteractionMode === "zoom"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "zoom",
});
}}
/>
</Tooltip>
</ButtonGroup>
<Subset
subsetPossible={subsetPossible}
subsetResetPossible={subsetResetPossible}
handleSubset={this.handleSubset}
handleSubsetReset={this.handleSubsetReset}
/>
{disableDiffexp ? null : <DiffexpButtons />}
</div>
);
}
}
export default MenuBar;
-392
View File
@@ -1,392 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
import * as globals from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
import actions from "../../actions";
import Clip from "./clip";
import AuthButtons from "./authButtons";
import Subset from "./subset";
import UndoRedoReset from "./undoRedo";
import DiffexpButtons from "./diffexpButtons";
import { getEmbSubsetView } from "../../util/stateManager/viewStackHelpers";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Defa... Remove this comment to see the full error message
const { annoMatrix } = state;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const crossfilter = (state as any).obsCrossfilter;
const selectedCount = crossfilter.countSelected();
const subsetPossible =
selectedCount !== 0 && selectedCount !== crossfilter.size(); // ie, not all and not none are selected
const embSubsetView = getEmbSubsetView(annoMatrix);
const subsetResetPossible = !embSubsetView
? annoMatrix.nObs !== annoMatrix.schema.dataframe.nObs
: annoMatrix.nObs !== embSubsetView.nObs;
return {
subsetPossible,
subsetResetPossible,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
graphInteractionMode: (state as any).controls.graphInteractionMode,
clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)),
clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)),
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userDefinedGenes: (state as any).controls.userDefinedGenes,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colorAccessor: (state as any).colors.colorAccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
libraryVersions: (state as any).config?.library_versions,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
auth: (state as any).config?.authentication,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
userInfo: (state as any).userInfo,
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
undoDisabled: state["@@undoable/past"].length === 0,
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
redoDisabled: state["@@undoable/future"].length === 0,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
aboutLink: (state as any).config?.links?.["about-dataset"],
disableDiffexp:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.["disable-diffexp"] ?? false,
diffexpMayBeSlow:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(state as any).config?.parameters?.["diffexp-may-be-slow"] ?? false,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
showCentroidLabels: (state as any).centroidLabels.showLabels,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
tosURL: (state as any).config?.parameters?.about_legal_tos,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
privacyURL: (state as any).config?.parameters?.about_legal_privacy,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
categoricalSelection: (state as any).categoricalSelection,
};
})
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class MenuBar extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static isValidDigitKeyEvent(e: any) {
/*
Return true if this event is necessary to enter a percent number input.
Return false if not.
Returns true for events with keys: backspace, control, alt, meta, [0-9],
or events that don't have a key.
*/
if (e.key === null) return true;
if (e.ctrlKey || e.altKey || e.metaKey) return true;
// concept borrowed from blueprint's numericInputUtils:
// keys that print a single character when pressed have a `key` name of
// length 1. every other key has a longer `key` name (e.g. "Backspace",
// "ArrowUp", "Shift"). since none of those keys can print a character
// to the field--and since they may have important native behaviors
// beyond printing a character--we don't want to disable their effects.
const isSingleCharKey = e.key.length === 1;
if (!isSingleCharKey) return true;
const key = e.key.charCodeAt(0) - 48; /* "0" */
return key >= 0 && key <= 9;
}
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
super(props);
this.state = {
pendingClipPercentiles: null,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
isClipDisabled = () => {
/*
return true if clip button should be disabled.
*/
const { pendingClipPercentiles } = this.state;
const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin;
const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax;
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message
clipPercentileMin: currentClipMin,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message
clipPercentileMax: currentClipMax,
} = this.props;
// if you change this test, be careful with logic around
// comparisons between undefined / NaN handling.
const isDisabled =
!(clipPercentileMin < clipPercentileMax) ||
(clipPercentileMin === currentClipMin &&
clipPercentileMax === currentClipMax);
return isDisabled;
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleClipOnKeyPress = (e: any) => {
/*
allow only numbers, plus other critical keys which
may be required to make a number
*/
if (!MenuBar.isValidDigitKeyEvent(e)) {
e.preventDefault();
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleClipPercentileMinValueChange = (v: any) => {
/*
Ignore anything that isn't a legit number
*/
if (!Number.isFinite(v)) return;
const { pendingClipPercentiles } = this.state;
const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax;
/*
clamp to [0, currentClipPercentileMax]
*/
if (v <= 0) v = 0;
if (v > 100) v = 100;
const clipPercentileMin = Math.round(v); // paranoia
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleClipPercentileMaxValueChange = (v: any) => {
/*
Ignore anything that isn't a legit number
*/
if (!Number.isFinite(v)) return;
const { pendingClipPercentiles } = this.state;
const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin;
/*
clamp to [0, 100]
*/
if (v < 0) v = 0;
if (v > 100) v = 100;
const clipPercentileMax = Math.round(v); // paranoia
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleClipCommit = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
const { pendingClipPercentiles } = this.state;
const { clipPercentileMin, clipPercentileMax } = pendingClipPercentiles;
const min = clipPercentileMin / 100;
const max = clipPercentileMax / 100;
dispatch(actions.clipAction(min, max));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleClipOpening = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message
const { clipPercentileMin, clipPercentileMax } = this.props;
this.setState({
pendingClipPercentiles: { clipPercentileMin, clipPercentileMax },
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleClipClosing = () => {
this.setState({ pendingClipPercentiles: null });
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleCentroidChange = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, showCentroidLabels } = this.props;
dispatch({
type: "show centroid labels for category",
showLabels: !showCentroidLabels,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSubset = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch(actions.subsetAction());
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleSubsetReset = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch(actions.resetSubsetAction());
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'disableDiffexp' does not exist on type '... Remove this comment to see the full error message
disableDiffexp,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'undoDisabled' does not exist on type 'Re... Remove this comment to see the full error message
undoDisabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'redoDisabled' does not exist on type 'Re... Remove this comment to see the full error message
redoDisabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
selectionTool,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message
clipPercentileMin,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message
clipPercentileMax,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
graphInteractionMode,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'showCentroidLabels' does not exist on ty... Remove this comment to see the full error message
showCentroidLabels,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
categoricalSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
colorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetPossible' does not exist on type '... Remove this comment to see the full error message
subsetPossible,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetResetPossible' does not exist on t... Remove this comment to see the full error message
subsetResetPossible,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'userInfo' does not exist on type 'Readon... Remove this comment to see the full error message
userInfo,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'auth' does not exist on type 'Readonly<{... Remove this comment to see the full error message
auth,
} = this.props;
const { pendingClipPercentiles } = this.state;
const isColoredByCategorical = !!categoricalSelection?.[colorAccessor];
// constants used to create selection tool button
const [selectionTooltip, selectionButtonIcon] =
selectionTool === "brush"
? ["Brush selection", "Lasso selection"]
: ["select", "polygon-filter"];
return (
<div
style={{
position: "absolute",
right: 8,
top: 0,
display: "flex",
flexDirection: "row-reverse",
alignItems: "flex-start",
flexWrap: "wrap",
justifyContent: "flex-start",
zIndex: 3,
}}
>
<AuthButtons {...{ auth, userInfo }} />
<UndoRedoReset
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ dispatch: any; undoDisabled: any; redoDisa... Remove this comment to see the full error message
dispatch={dispatch}
undoDisabled={undoDisabled}
redoDisabled={redoDisabled}
/>
<Clip
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ pendingClipPercentiles: any; clipPercentil... Remove this comment to see the full error message
pendingClipPercentiles={pendingClipPercentiles}
clipPercentileMin={clipPercentileMin}
clipPercentileMax={clipPercentileMax}
handleClipOpening={this.handleClipOpening}
handleClipClosing={this.handleClipClosing}
handleClipCommit={this.handleClipCommit}
isClipDisabled={this.isClipDisabled}
handleClipOnKeyPress={this.handleClipOnKeyPress}
handleClipPercentileMaxValueChange={
this.handleClipPercentileMaxValueChange
}
handleClipPercentileMinValueChange={
this.handleClipPercentileMinValueChange
}
/>
<Tooltip
content="When a category is colored by, show labels on the graph"
position="bottom"
disabled={graphInteractionMode === "zoom"}
>
<AnchorButton
className={styles.menubarButton}
type="button"
data-testid="centroid-label-toggle"
icon="property"
onClick={this.handleCentroidChange}
active={showCentroidLabels}
intent={showCentroidLabels ? "primary" : "none"}
disabled={!isColoredByCategorical}
/>
</Tooltip>
<ButtonGroup className={styles.menubarButton}>
<Tooltip
content={selectionTooltip}
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-lasso"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'IconName ... Remove this comment to see the full error message
icon={selectionButtonIcon}
active={graphInteractionMode === "select"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "select",
});
}}
/>
</Tooltip>
<Tooltip
content="Drag to pan, scroll to zoom"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-pan-zoom"
icon="zoom-in"
active={graphInteractionMode === "zoom"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "zoom",
});
}}
/>
</Tooltip>
</ButtonGroup>
<Subset
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ subsetPossible: any; subsetResetPossible: ... Remove this comment to see the full error message
subsetPossible={subsetPossible}
subsetResetPossible={subsetResetPossible}
handleSubset={this.handleSubset}
handleSubsetReset={this.handleSubsetReset}
/>
{disableDiffexp ? null : <DiffexpButtons />}
</div>
);
}
}
export default MenuBar;
@@ -1,18 +1,13 @@
import React from "react";
import { AnchorButton, ButtonGroup, Tooltip } from "@blueprintjs/core";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
import * as globals from "../../globals";
const Subset = React.memo((props) => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetPossible' does not exist on type '... Remove this comment to see the full error message
subsetPossible,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetResetPossible' does not exist on t... Remove this comment to see the full error message
subsetResetPossible,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubset' does not exist on type '{ ... Remove this comment to see the full error message
handleSubset,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubsetReset' does not exist on typ... Remove this comment to see the full error message
handleSubsetReset,
} = props;
@@ -2,11 +2,9 @@ import React from "react";
import { AnchorButton, ButtonGroup, Tooltip } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { tooltipHoverOpenDelay } from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message
import styles from "./menubar.css";
const UndoRedo = React.memo((props) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'undoDisabled' does not exist on type '{ ... Remove this comment to see the full error message
const { undoDisabled, redoDisabled, dispatch } = props;
return (
<ButtonGroup className={`${styles.menubarButton}`}>
@@ -7,18 +7,12 @@ import {
} from "@blueprintjs/core";
export default class MiniHistogram extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
canvasRef: any;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
constructor(props: any) {
constructor(props) {
super(props);
this.canvasRef = React.createRef();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
drawHistogram = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'xScale' does not exist on type 'Readonly... Remove this comment to see the full error message
const { xScale, yScale, bins, width, height } = this.props;
if (!bins) return;
@@ -41,14 +35,11 @@ export default class MiniHistogram extends React.PureComponent {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount = () => {
this.drawHistogram();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
componentDidUpdate = (prevProps: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsOrVarContinuousFieldDisplayName' does... Remove this comment to see the full error message
componentDidUpdate = (prevProps) => {
const { obsOrVarContinuousFieldDisplayName, bins } = this.props;
if (
prevProps.obsOrVarContinuousFieldDisplayName !==
@@ -58,18 +49,9 @@ export default class MiniHistogram extends React.PureComponent {
this.drawHistogram();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'domainLabel' does not exist on type 'Rea... Remove this comment to see the full error message
domainLabel,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsOrVarContinuousFieldDisplayName' does... Remove this comment to see the full error message
obsOrVarContinuousFieldDisplayName,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
width,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message
height,
} = this.props;
const { domainLabel, obsOrVarContinuousFieldDisplayName, width, height } =
this.props;
return (
<Popover
@@ -0,0 +1,72 @@
import React from "react";
export default class MiniStackedBar extends React.PureComponent {
constructor(props) {
super(props);
this.canvasRef = React.createRef();
}
drawStacks = () => {
const {
domainValues,
scale,
domain,
colorTable,
occupancy,
width,
height,
} = this.props;
if (!colorTable || !domainValues) return;
const { scale: colorScale } = colorTable;
const ctx = this.canvasRef?.current.getContext("2d");
ctx.clearRect(0, 0, width, height);
let currentOffset = 0;
let occupancyValue;
let scaledValue;
let value;
for (let i = 0, { length } = domainValues; i < length; i += 1) {
value = domainValues[i];
occupancyValue = occupancy.get(value);
scaledValue = scale(occupancyValue);
ctx.fillStyle = occupancyValue
? colorScale(domain.indexOf(value))
: "rgb(255,255,255)";
ctx.fillRect(currentOffset, 0, occupancyValue ? scaledValue : 0, height);
currentOffset += occupancyValue ? scaledValue : 0;
}
};
componentDidUpdate = (prevProps) => {
const { occupancy } = this.props;
if (occupancy !== prevProps.occupancy) this.drawStacks();
};
componentDidMount = () => {
this.drawStacks();
};
render() {
const { width, height } = this.props;
const { canvas } = this;
if (canvas) canvas.getContext("2d").clearRect(0, 0, width, height);
return (
<canvas
style={{
marginRight: 5,
width,
height,
}}
width={width}
height={height}
ref={this.canvasRef}
/>
);
}
}
@@ -1,90 +0,0 @@
import React from "react";
export default class MiniStackedBar extends React.PureComponent {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
canvasRef: any;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
constructor(props: any) {
super(props);
this.canvasRef = React.createRef();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
drawStacks = () => {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'domainValues' does not exist on type 'Re... Remove this comment to see the full error message
domainValues,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'Readonly<... Remove this comment to see the full error message
scale,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type 'Readonly... Remove this comment to see the full error message
domain,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message
colorTable,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'occupancy' does not exist on type 'Reado... Remove this comment to see the full error message
occupancy,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
width,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message
height,
} = this.props;
if (!colorTable || !domainValues) return;
const { scale: colorScale } = colorTable;
const ctx = this.canvasRef?.current.getContext("2d");
ctx.clearRect(0, 0, width, height);
let currentOffset = 0;
let occupancyValue;
let scaledValue;
let value;
for (let i = 0, { length } = domainValues; i < length; i += 1) {
value = domainValues[i];
occupancyValue = occupancy.get(value);
scaledValue = scale(occupancyValue);
ctx.fillStyle = occupancyValue
? colorScale(domain.indexOf(value))
: "rgb(255,255,255)";
ctx.fillRect(currentOffset, 0, occupancyValue ? scaledValue : 0, height);
currentOffset += occupancyValue ? scaledValue : 0;
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
componentDidUpdate = (prevProps: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'occupancy' does not exist on type 'Reado... Remove this comment to see the full error message
const { occupancy } = this.props;
if (occupancy !== prevProps.occupancy) this.drawStacks();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount = () => {
this.drawStacks();
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
const { width, height } = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'canvas' does not exist on type 'MiniStac... Remove this comment to see the full error message
const { canvas } = this;
if (canvas) canvas.getContext("2d").clearRect(0, 0, width, height);
return (
<canvas
style={{
marginRight: 5,
width,
height,
}}
width={width}
height={height}
ref={this.canvasRef}
/>
);
}
}
@@ -3,15 +3,11 @@ import { connect } from "react-redux";
import GeneExpression from "../geneExpression";
import * as globals from "../../globals";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor,
scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
}))
class RightSidebar extends React.Component {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
return (
<div
@@ -1,7 +1,6 @@
import { glPointFlags, glPointSize } from "../../util/glHelpers";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export default function drawPointsRegl(regl: any) {
export default function drawPointsRegl(regl) {
return regl({
vert: `
precision mediump float;
@@ -8,7 +8,6 @@ import memoize from "memoize-one";
import Async from "react-async";
import * as globals from "../../globals";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './scatterplot.css' or its corr... Remove this comment to see the full error message
import styles from "./scatterplot.css";
import _drawPoints from "./drawPointsRegl";
import { margin, width, height } from "./util";
@@ -22,10 +21,8 @@ import {
flagSelected,
flagHighlight,
} from "../../util/glHelpers";
import { Dataframe, DataframeColumn } from "../../util/dataframe";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function createProjectionTF(viewportWidth: any, viewportHeight: any) {
function createProjectionTF(viewportWidth, viewportHeight) {
/*
the projection transform accounts for the screen size & other layout
*/
@@ -33,47 +30,33 @@ function createProjectionTF(viewportWidth: any, viewportHeight: any) {
return mat3.projection(m, viewportWidth, viewportHeight);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function getScale(col: DataframeColumn, rangeMin: any, rangeMax: any) {
function getScale(col, rangeMin, rangeMax) {
if (!col) return null;
const { min, max } = col.summarizeContinuous();
const { min, max } = col.summarize();
return d3.scaleLinear().domain([min, max]).range([rangeMin, rangeMax]);
}
const getXScale = memoize(getScale);
const getYScale = memoize(getScale);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
const { obsCrossfilter: crossfilter } = state;
const {
scatterplotXXaccessor,
scatterplotYYaccessor,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
} = (state as any).controls;
const { scatterplotXXaccessor, scatterplotYYaccessor } = state.controls;
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
pointDilation: (state as any).pointDilation,
annoMatrix: state.annoMatrix,
colors: state.colors,
pointDilation: state.pointDilation,
// Accessors are var/gene names (strings)
scatterplotXXaccessor,
scatterplotYYaccessor,
crossfilter,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
genesets: state.genesets.genesets,
};
})
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Scatterplot extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static createReglState(canvas: any) {
class Scatterplot extends React.PureComponent {
static createReglState(canvas) {
/*
Must be created for each canvas
*/
@@ -87,11 +70,8 @@ class Scatterplot extends React.PureComponent<{}, State> {
const drawPoints = _drawPoints(regl);
// preallocate webgl buffers
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const pointBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const colorBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const flagBuffer = regl.buffer();
return {
@@ -103,20 +83,10 @@ class Scatterplot extends React.PureComponent<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
axes: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
reglCanvas: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
renderCache: any;
computePointPositions = memoize((X, Y, xScale, yScale) => {
const positions = new Float32Array(2 * X.length);
for (let i = 0, len = X.length; i < len; i += 1) {
@@ -213,8 +183,7 @@ class Scatterplot extends React.PureComponent<{}, State> {
}
);
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
const viewport = this.getViewportDimensions();
this.axes = false;
@@ -229,19 +198,16 @@ class Scatterplot extends React.PureComponent<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
// this affect point render size for the scatterplot
window.addEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
setReglCanvas = (canvas: any) => {
setReglCanvas = (canvas) => {
this.reglCanvas = canvas;
if (canvas) {
// no need to update this state if we are detaching.
@@ -251,13 +217,11 @@ class Scatterplot extends React.PureComponent<{}, State> {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getViewportDimensions = () => ({
height: window.innerHeight,
width: window.innerWidth,
});
height: window.innerHeight,
width: window.innerWidth,
});
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleResize = () => {
const { state } = this.state;
const viewport = this.getViewportDimensions();
@@ -267,8 +231,7 @@ class Scatterplot extends React.PureComponent<{}, State> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
fetchAsyncProps = async (props) => {
const {
scatterplotXXaccessor,
scatterplotYYaccessor,
@@ -326,9 +289,7 @@ class Scatterplot extends React.PureComponent<{}, State> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
createXQuery(geneName: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
createXQuery(geneName) {
const { annoMatrix } = this.props;
const { schema } = annoMatrix;
const varIndex = schema?.annotations?.var?.index;
@@ -345,19 +306,15 @@ class Scatterplot extends React.PureComponent<{}, State> {
];
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
createColorByQuery(colors: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
createColorByQuery(colors) {
const { annoMatrix, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateColorTable(colors: any, colorDf: any) {
updateColorTable(colors, colorDf) {
/* update color table state */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix } = this.props;
const { schema } = annoMatrix;
const { colorAccessor, userColors, colorMode } = colors;
@@ -370,42 +327,40 @@ class Scatterplot extends React.PureComponent<{}, State> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async fetchData(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
scatterplotXXaccessor: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
scatterplotYYaccessor: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colors: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointDilation: any
): Promise<
[Dataframe, Dataframe, Dataframe | null, Dataframe | null]
> {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
scatterplotXXaccessor,
scatterplotYYaccessor,
colors,
pointDilation
) {
const { annoMatrix } = this.props;
const { metadataField: pointDilationAccessor } = pointDilation;
const promises = [];
// X and Y dimensions
promises.push(
annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor))
);
promises.push(
annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor))
);
// color
const query = this.createColorByQuery(colors);
if (query) {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
const promises: [Dataframe, Dataframe, Dataframe | null, Dataframe | null] =
[
// @ts-expect-error ts-migrate(2488) FIXME: Type '(string | { where: { field: string; column: ... Remove this comment to see the full error message
annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor)),
annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor)),
query ? annoMatrix.fetch(...query) : Promise.resolve(null),
pointDilationAccessor
? annoMatrix.fetch("obs", pointDilationAccessor)
: Promise.resolve(null),
];
// point highlighting
if (pointDilationAccessor) {
promises.push(annoMatrix.fetch("obs", pointDilationAccessor));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all<
Dataframe,
Dataframe,
Dataframe | null,
Dataframe | null
>(promises);
return Promise.all(promises);
}
renderCanvas = renderThrottle(() => {
@@ -427,8 +382,7 @@ class Scatterplot extends React.PureComponent<{}, State> {
);
});
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateReglAndRender(newRenderCache: any) {
updateReglAndRender(newRenderCache) {
const { positions, colors, flags } = newRenderCache;
this.renderCache = newRenderCache;
const { pointBuffer, colorBuffer, flagBuffer } = this.state;
@@ -438,22 +392,14 @@ class Scatterplot extends React.PureComponent<{}, State> {
this.renderCanvas();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderPoints(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
regl: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
drawPoints: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
flagBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
projectionTF: any
regl,
drawPoints,
flagBuffer,
colorBuffer,
pointBuffer,
projectionTF
) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix } = this.props;
if (!this.reglCanvas || !annoMatrix) return;
@@ -479,22 +425,14 @@ class Scatterplot extends React.PureComponent<{}, State> {
regl._gl.flush();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message
scatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotYYaccessor' does not exist on... Remove this comment to see the full error message
scatterplotYYaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message
crossfilter,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on type 'R... Remove this comment to see the full error message
pointDilation,
} = this.props;
const { minimized, regl, viewport } = this.state;
@@ -561,7 +499,6 @@ class Scatterplot extends React.PureComponent<{}, State> {
style={{
marginLeft: margin.left,
marginTop: margin.top,
// @ts-expect-error ts-migrate(2322) FIXME: Type '"none" | null' is not assignable to type 'Di... Remove this comment to see the full error message
display: minimized ? "none" : null,
}}
ref={this.setReglCanvas}
@@ -588,14 +525,11 @@ class Scatterplot extends React.PureComponent<{}, State> {
}
return (
<ScatterplotAxis
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ minimized: any; scatterplotYYaccessor: any... Remove this comment to see the full error message
minimized={minimized}
scatterplotYYaccessor={scatterplotYYaccessor}
scatterplotXXaccessor={scatterplotXXaccessor}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
xScale={(asyncProps as any).xScale}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
yScale={(asyncProps as any).yScale}
xScale={asyncProps.xScale}
yScale={asyncProps.yScale}
/>
);
}}
@@ -611,15 +545,10 @@ export default Scatterplot;
const ScatterplotAxis = React.memo(
({
// @ts-expect-error ts-migrate(2339) FIXME: Property 'minimized' does not exist on type '{ chi... Remove this comment to see the full error message
minimized,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotYYaccessor' does not exist on... Remove this comment to see the full error message
scatterplotYYaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message
scatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'xScale' does not exist on type '{ childr... Remove this comment to see the full error message
xScale,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yScale' does not exist on type '{ childr... Remove this comment to see the full error message
yScale,
}) => {
/*
@@ -643,9 +572,7 @@ const ScatterplotAxis = React.memo(
// the axes are much cleaner and easier now. No need to rotate and orient
// the axis, just call axisBottom, axisLeft etc.
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const xAxis = d3.axisBottom().ticks(7).scale(xScale);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const yAxis = d3.axisLeft().ticks(7).scale(yScale);
// adding axes is also simpler now, just translate x-axis to (0,height)
@@ -688,7 +615,6 @@ const ScatterplotAxis = React.memo(
height={height + margin.top + margin.bottom}
data-testid="scatterplot-svg"
style={{
// @ts-expect-error ts-migrate(2322) FIXME: Type '"none" | null' is not assignable to type 'Di... Remove this comment to see the full error message
display: minimized ? "none" : null,
}}
>
@@ -10,25 +10,13 @@ import {
} from "@blueprintjs/core";
import { storageGet, storageSet, KEYS } from "../util/localStorage";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
tosURL: (state as any).config?.parameters?.about_legal_tos,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
privacyURL: (state as any).config?.parameters?.about_legal_privacy,
tosURL: state.config?.parameters?.about_legal_tos,
privacyURL: state.config?.parameters?.about_legal_privacy,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class TermsPrompt extends React.PureComponent<{}, State> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
drawerClose: any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
class TermsPrompt extends React.PureComponent {
constructor(props) {
super(props);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message
const { tosURL, privacyURL } = this.props;
const cookieDecision = storageGet(KEYS.COOKIE_DECISION, null);
const hasDecided = cookieDecision !== null;
@@ -39,7 +27,6 @@ class TermsPrompt extends React.PureComponent<{}, State> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
const { hasDecided, isEnabled } = this.state;
if (isEnabled && !hasDecided) {
@@ -47,14 +34,11 @@ class TermsPrompt extends React.PureComponent<{}, State> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleOK = () => {
this.setState({ isOpen: false });
storageSet(KEYS.COOKIE_DECISION, "yes");
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cookieDecisionCallback' does not exist o... Remove this comment to see the full error message
if (window.cookieDecisionCallback instanceof Function) {
try {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cookieDecisionCallback' does not exist o... Remove this comment to see the full error message
window.cookieDecisionCallback();
} catch (e) {
// continue
@@ -62,15 +46,12 @@ class TermsPrompt extends React.PureComponent<{}, State> {
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleNo = () => {
this.setState({ isOpen: false });
storageSet(KEYS.COOKIE_DECISION, "no");
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderTos() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message
const { tosURL } = this.props;
if (!tosURL) return null;
return (
@@ -93,9 +74,7 @@ class TermsPrompt extends React.PureComponent<{}, State> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderPrivacy() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'privacyURL' does not exist on type 'Read... Remove this comment to see the full error message
const { privacyURL } = this.props;
if (!privacyURL) return null;
return (
@@ -117,22 +96,18 @@ class TermsPrompt extends React.PureComponent<{}, State> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const { isOpen, isEnabled } = this.state;
if (!isEnabled || !isOpen) return null;
return (
<Drawer
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element; onclose: any; isOpen: a... Remove this comment to see the full error message
onclose={this.drawerClose}
isOpen={isOpen}
size="120px"
position={Position.BOTTOM}
canOutsideClickClose={false}
hasBackdrop
/* if the user can't use the app or click outside to dismiss, that should be visually represented with a backdrop */ enforceFocus={
false
}
hasBackdrop /* if the user can't use the app or click outside to dismiss, that should be visually represented with a backdrop */
enforceFocus={false}
autoFocus={false}
portal={false}
>
@@ -168,4 +143,5 @@ class TermsPrompt extends React.PureComponent<{}, State> {
);
}
}
export default TermsPrompt;
@@ -0,0 +1,22 @@
export const KEYS = {
COOKIE_DECISION: "cxg.cookieDecision",
LOGIN_PROMPT: "cxg.LOGIN_PROMPT",
};
export function storageGet(key, defaultValue = null) {
try {
const val = window.localStorage.getItem(key);
if (val === null) return defaultValue;
return val;
} catch (e) {
return defaultValue;
}
}
export function storageSet(key, value) {
try {
window.localStorage.setItem(key, value);
} catch {
// continue
}
}
@@ -1,24 +0,0 @@
export const KEYS = {
COOKIE_DECISION: "cxg.cookieDecision",
LOGIN_PROMPT: "cxg.LOGIN_PROMPT",
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function storageGet(key: any, defaultValue = null) {
try {
const val = window.localStorage.getItem(key);
if (val === null) return defaultValue;
return val;
} catch (e) {
return defaultValue;
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function storageSet(key: any, value: any) {
try {
window.localStorage.setItem(key, value);
} catch {
// continue
}
}
@@ -32,8 +32,7 @@ const SECOND_HALF_INNER_STYLE = {
right: 0,
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export default (props: any) => {
export default (props) => {
const { children, isGenesetDescription, tooltipAddendum = "" } = props;
// Truncate only support a single child with a text child
@@ -71,12 +70,9 @@ export default (props: any) => {
const truncatedJSX = (
<span style={splitStyle}>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ overflow: string; textOverflow: string; wh... Remove this comment to see the full error message */}
<span style={FIRST_HALF_STYLE}>{firstString}</span>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ position: string; overflow: string; whiteS... Remove this comment to see the full error message */}
<span style={SECOND_HALF_STYLE}>
<span style={SECOND_HALF_SPACING_STYLE}>{secondString}</span>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ color: any; position: string; right: numbe... Remove this comment to see the full error message */}
<span style={secondHalfContentStyle}>{secondString}</span>
</span>
</span>
@@ -106,7 +102,6 @@ export default (props: any) => {
: `${originalString}${tooltipAddendum}`
}
hoverOpenDelay={tooltipHoverOpenDelayQuick}
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
targetProps={{ style: children.props.style }}
>
{newChildren}