TS migration. #2288. (#2328)

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

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

Co-authored-by: ts-migrate <>

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

Co-authored-by: ts-migrate <>

* Corrected files mangled by ts-migrate.

* Updated lint config, minor linting.

* Re-enabled Husky.

* Updated tests and config.

* Reverted webpack devtool config.

* Removed obsolete snapshots.

* Added annotations snap.

* Updated tsconfig includes wrt linting.

* Removed ts-migrate.

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
Mim Hastie
2021-07-26 20:18:17 +00:00
committed by GitHub
co-authored by ts-migrate Timmy Huang
parent 7328cbdbd5
commit 934cc5c69b
206 changed files with 4719 additions and 2085 deletions
@@ -18,12 +18,17 @@ import {
import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config"; import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config";
export async function drag(testId, start, end, lasso = false) { export async function drag(testId: any, start: any, end: any, lasso = false) {
const layout = await waitByID(testId); const layout = await waitByID(testId);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const elBox = await layout.boxModel(); const elBox = await layout.boxModel();
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const x1 = elBox.content[0].x + start.x; const x1 = elBox.content[0].x + start.x;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const x2 = elBox.content[0].x + end.x; const x2 = elBox.content[0].x + end.x;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const y1 = elBox.content[0].y + start.y; const y1 = elBox.content[0].y + start.y;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const y2 = elBox.content[0].y + end.y; const y2 = elBox.content[0].y + end.y;
await page.mouse.move(x1, y1); await page.mouse.move(x1, y1);
await page.mouse.down(); await page.mouse.down();
@@ -38,7 +43,7 @@ export async function drag(testId, start, end, lasso = false) {
await page.mouse.up(); await page.mouse.up();
} }
export async function clickOnCoordinate(testId, coord) { export async function clickOnCoordinate(testId: any, coord: any) {
const layout = await expect(page).toMatchElement(getTestId(testId)); const layout = await expect(page).toMatchElement(getTestId(testId));
const elBox = await layout.boxModel(); const elBox = await layout.boxModel();
@@ -51,11 +56,12 @@ export async function clickOnCoordinate(testId, coord) {
await page.mouse.click(x, y); await page.mouse.click(x, y);
} }
export async function getAllHistograms(testclass, testIds) { export async function getAllHistograms(testclass: any, testIds: any) {
const histTestIds = testIds.map((tid) => `histogram-${tid}`); const histTestIds = testIds.map((tid: any) => `histogram-${tid}`);
// these load asynchronously, so we need to wait for each histogram individually, // these load asynchronously, so we need to wait for each histogram individually,
// and they may be quite slow in some cases. // and they may be quite slow in some cases.
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
await waitForAllByIds(histTestIds, { timeout: 4 * 60 * 1000 }); await waitForAllByIds(histTestIds, { timeout: 4 * 60 * 1000 });
const allHistograms = await getAllByClass(testclass); const allHistograms = await getAllByClass(testclass);
@@ -71,7 +77,7 @@ export async function getAllHistograms(testclass, testIds) {
return testIDs.map((id) => id.replace(/^histogram-/, "")); return testIDs.map((id) => id.replace(/^histogram-/, ""));
} }
export async function getAllCategoriesAndCounts(category) { export async function getAllCategoriesAndCounts(category: any) {
// these load asynchronously, so we have to wait for the specific category. // these load asynchronously, so we have to wait for the specific category.
await waitByID(`category-${category}`); await waitByID(`category-${category}`);
@@ -80,13 +86,14 @@ export async function getAllCategoriesAndCounts(category) {
(rows) => (rows) =>
Object.fromEntries( Object.fromEntries(
rows.map((row) => { rows.map((row) => {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const cat = row const cat = row
.querySelector("[data-testclass='categorical-value']") .querySelector("[data-testclass='categorical-value']")
.getAttribute("aria-label"); .getAttribute("aria-label");
const count = row.querySelector( const count = (row.querySelector(
"[data-testclass='categorical-value-count']" "[data-testclass='categorical-value-count']"
).innerText; ) as any).innerText;
return [cat, count]; return [cat, count];
}) })
@@ -94,12 +101,12 @@ export async function getAllCategoriesAndCounts(category) {
); );
} }
export async function getCellSetCount(num) { export async function getCellSetCount(num: any) {
await clickOn(`cellset-button-${num}`); await clickOn(`cellset-button-${num}`);
return getOneElementInnerText(`[data-testid='cellset-count-${num}']`); return getOneElementInnerText(`[data-testid='cellset-count-${num}']`);
} }
export async function resetCategory(category) { export async function resetCategory(category: any) {
const checkboxId = `${category}:category-select`; const checkboxId = `${category}:category-select`;
await waitByID(checkboxId); await waitByID(checkboxId);
const checkedPseudoclass = await page.$eval( const checkedPseudoclass = await page.$eval(
@@ -110,6 +117,7 @@ export async function resetCategory(category) {
const categoryRow = await waitByID(`${category}:category-expand`); const categoryRow = await waitByID(`${category}:category-expand`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const isExpanded = await categoryRow.$( const isExpanded = await categoryRow.$(
"[data-testclass='category-expand-is-expanded']" "[data-testclass='category-expand-is-expanded']"
); );
@@ -117,16 +125,26 @@ export async function resetCategory(category) {
if (isExpanded) await clickOn(`${category}:category-expand`); if (isExpanded) await clickOn(`${category}:category-expand`);
} }
export async function calcCoordinate(testId, xAsPercent, yAsPercent) { export async function calcCoordinate(
testId: any,
xAsPercent: any,
yAsPercent: any
) {
const el = await waitByID(testId); const el = await waitByID(testId);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const size = await el.boxModel(); const size = await el.boxModel();
return { return {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
x: Math.floor(size.width * xAsPercent), x: Math.floor(size.width * xAsPercent),
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
y: Math.floor(size.height * yAsPercent), y: Math.floor(size.height * yAsPercent),
}; };
} }
export async function calcDragCoordinates(testId, coordinateAsPercent) { export async function calcDragCoordinates(
testId: any,
coordinateAsPercent: any
) {
return { return {
start: await calcCoordinate( start: await calcCoordinate(
testId, testId,
@@ -141,7 +159,7 @@ export async function calcDragCoordinates(testId, coordinateAsPercent) {
}; };
} }
export async function selectCategory(category, values, reset = true) { export async function selectCategory(category: any, values: any, reset = true) {
if (reset) await resetCategory(category); if (reset) await resetCategory(category);
await clickOn(`${category}:category-expand`); await clickOn(`${category}:category-expand`);
@@ -152,8 +170,9 @@ export async function selectCategory(category, values, reset = true) {
} }
} }
export async function expandCategory(category) { export async function expandCategory(category: any) {
const expand = await waitByID(`${category}:category-expand`); const expand = await waitByID(`${category}:category-expand`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const notExpanded = await expand.$( const notExpanded = await expand.$(
"[data-testclass='category-expand-is-not-expanded']" "[data-testclass='category-expand-is-not-expanded']"
); );
@@ -167,7 +186,7 @@ export async function clip(min = 0, max = 100) {
await clickOn("clip-commit"); await clickOn("clip-commit");
} }
export async function createCategory(categoryName) { export async function createCategory(categoryName: any) {
await clickOnUntil("open-annotation-dialog", async () => { await clickOnUntil("open-annotation-dialog", async () => {
await expect(page).toMatchElement(getTestId("new-category-name")); await expect(page).toMatchElement(getTestId("new-category-name"));
}); });
@@ -182,17 +201,18 @@ export async function createCategory(categoryName) {
*/ */
export async function colorByGeneset(genesetName) { export async function colorByGeneset(genesetName: any) {
await clickOn(`${genesetName}:colorby-entire-geneset`); await clickOn(`${genesetName}:colorby-entire-geneset`);
} }
export async function colorByGene(gene) { export async function colorByGene(gene: any) {
await clickOn(`colorby-${gene}`); await clickOn(`colorby-${gene}`);
} }
export async function assertColorLegendLabel(label) { export async function assertColorLegendLabel(label: any) {
const handle = await waitByID("continuous_legend_color_by_label"); const handle = await waitByID("continuous_legend_color_by_label");
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const result = await handle.evaluate((node) => { const result = await handle.evaluate((node) => {
return node.getAttribute("aria-label"); return node.getAttribute("aria-label");
}); });
@@ -200,15 +220,16 @@ export async function assertColorLegendLabel(label) {
return expect(result).toBe(label); return expect(result).toBe(label);
} }
export async function expandGeneset(genesetName) { export async function expandGeneset(genesetName: any) {
const expand = await waitByID(`${genesetName}:geneset-expand`); const expand = await waitByID(`${genesetName}:geneset-expand`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const notExpanded = await expand.$( const notExpanded = await expand.$(
"[data-testclass='geneset-expand-is-not-expanded']" "[data-testclass='geneset-expand-is-not-expanded']"
); );
if (notExpanded) await clickOn(`${genesetName}:geneset-expand`); if (notExpanded) await clickOn(`${genesetName}:geneset-expand`);
} }
export async function createGeneset(genesetName) { export async function createGeneset(genesetName: any) {
await clickOnUntil("open-create-geneset-dialog", async () => { await clickOnUntil("open-create-geneset-dialog", async () => {
await expect(page).toMatchElement(getTestId("create-geneset-input")); await expect(page).toMatchElement(getTestId("create-geneset-input"));
}); });
@@ -218,7 +239,7 @@ export async function createGeneset(genesetName) {
await waitByClass("autosave-complete"); await waitByClass("autosave-complete");
} }
export async function editGenesetName(genesetName, editText) { export async function editGenesetName(genesetName: any, editText: any) {
const editButton = `${genesetName}:edit-genesetName-mode`; const editButton = `${genesetName}:edit-genesetName-mode`;
const submitButton = `${genesetName}:submit-geneset`; const submitButton = `${genesetName}:submit-geneset`;
await clickOnUntil(`${genesetName}:see-actions`, async () => { await clickOnUntil(`${genesetName}:see-actions`, async () => {
@@ -229,7 +250,7 @@ export async function editGenesetName(genesetName, editText) {
await clickOn(submitButton); await clickOn(submitButton);
} }
export async function deleteGeneset(genesetName) { export async function deleteGeneset(genesetName: any) {
const targetId = `${genesetName}:delete-geneset`; const targetId = `${genesetName}:delete-geneset`;
await clickOnUntil(`${genesetName}:see-actions`, async () => { await clickOnUntil(`${genesetName}:see-actions`, async () => {
@@ -242,16 +263,18 @@ export async function deleteGeneset(genesetName) {
await waitByClass("autosave-complete"); await waitByClass("autosave-complete");
} }
export async function assertGenesetDoesNotExist(genesetName) { export async function assertGenesetDoesNotExist(genesetName: any) {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const result = await isElementPresent( const result = await isElementPresent(
getTestId(`${genesetName}:geneset-name`) getTestId(`${genesetName}:geneset-name`)
); );
await expect(result).toBe(false); await expect(result).toBe(false);
} }
export async function assertGenesetExists(genesetName) { export async function assertGenesetExists(genesetName: any) {
const handle = await waitByID(`${genesetName}:geneset-name`); const handle = await waitByID(`${genesetName}:geneset-name`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const result = await handle.evaluate((node) => { const result = await handle.evaluate((node) => {
return node.getAttribute("aria-label"); return node.getAttribute("aria-label");
}); });
@@ -265,7 +288,7 @@ export async function assertGenesetExists(genesetName) {
*/ */
export async function addGeneToSet(genesetName, geneToAddToSet) { export async function addGeneToSet(genesetName: any, geneToAddToSet: any) {
const submitButton = `${genesetName}:submit-gene`; const submitButton = `${genesetName}:submit-gene`;
await clickOn(`${genesetName}:add-new-gene-to-geneset`); await clickOn(`${genesetName}:add-new-gene-to-geneset`);
@@ -273,7 +296,7 @@ export async function addGeneToSet(genesetName, geneToAddToSet) {
await clickOn(submitButton); await clickOn(submitButton);
} }
export async function removeGene(geneSymbol) { export async function removeGene(geneSymbol: any) {
const targetId = `delete-from-geneset:${geneSymbol}`; const targetId = `delete-from-geneset:${geneSymbol}`;
await clickOn(targetId); await clickOn(targetId);
@@ -281,9 +304,10 @@ export async function removeGene(geneSymbol) {
await waitByClass("autosave-complete"); await waitByClass("autosave-complete");
} }
export async function assertGeneExistsInGeneset(geneSymbol) { export async function assertGeneExistsInGeneset(geneSymbol: any) {
const handle = await waitByID(`${geneSymbol}:gene-label`); const handle = await waitByID(`${geneSymbol}:gene-label`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const result = await handle.evaluate((node) => { const result = await handle.evaluate((node) => {
return node.getAttribute("aria-label"); return node.getAttribute("aria-label");
}); });
@@ -291,13 +315,14 @@ export async function assertGeneExistsInGeneset(geneSymbol) {
return expect(result).toBe(geneSymbol); return expect(result).toBe(geneSymbol);
} }
export async function assertGeneDoesNotExist(geneSymbol) { export async function assertGeneDoesNotExist(geneSymbol: any) {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const result = await isElementPresent(getTestId(`${geneSymbol}:gene-label`)); const result = await isElementPresent(getTestId(`${geneSymbol}:gene-label`));
await expect(result).toBe(false); await expect(result).toBe(false);
} }
export async function expandGene(geneSymbol) { export async function expandGene(geneSymbol: any) {
await clickOn(`maximize-${geneSymbol}`); await clickOn(`maximize-${geneSymbol}`);
} }
@@ -307,7 +332,7 @@ export async function expandGene(geneSymbol) {
*/ */
export async function duplicateCategory(categoryName) { export async function duplicateCategory(categoryName: any) {
await clickOn("open-annotation-dialog"); await clickOn("open-annotation-dialog");
await typeInto("new-category-name", categoryName); await typeInto("new-category-name", categoryName);
@@ -333,7 +358,10 @@ export async function duplicateCategory(categoryName) {
await waitByClass("autosave-complete"); await waitByClass("autosave-complete");
} }
export async function renameCategory(oldCategoryName, newCategoryName) { export async function renameCategory(
oldCategoryName: any,
newCategoryName: any
) {
await clickOn(`${oldCategoryName}:see-actions`); await clickOn(`${oldCategoryName}:see-actions`);
await clickOn(`${oldCategoryName}:edit-category-mode`); await clickOn(`${oldCategoryName}:edit-category-mode`);
await clearInputAndTypeInto( await clearInputAndTypeInto(
@@ -343,7 +371,7 @@ export async function renameCategory(oldCategoryName, newCategoryName) {
await clickOn(`${oldCategoryName}:submit-category-edit`); await clickOn(`${oldCategoryName}:submit-category-edit`);
} }
export async function deleteCategory(categoryName) { export async function deleteCategory(categoryName: any) {
const targetId = `${categoryName}:delete-category`; const targetId = `${categoryName}:delete-category`;
await clickOnUntil(`${categoryName}:see-actions`, async () => { await clickOnUntil(`${categoryName}:see-actions`, async () => {
@@ -352,10 +380,11 @@ export async function deleteCategory(categoryName) {
await clickOn(targetId); await clickOn(targetId);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
await assertCategoryDoesNotExist(); await assertCategoryDoesNotExist();
} }
export async function createLabel(categoryName, labelName) { export async function createLabel(categoryName: any, labelName: any) {
/** /**
* (thuang): This explicit wait is needed, since currently showing * (thuang): This explicit wait is needed, since currently showing
* the modal again quickly after the previous action dismissing the * the modal again quickly after the previous action dismissing the
@@ -380,13 +409,17 @@ export async function createLabel(categoryName, labelName) {
await clickOn(`${categoryName}:submit-label`); await clickOn(`${categoryName}:submit-label`);
} }
export async function deleteLabel(categoryName, labelName) { export async function deleteLabel(categoryName: any, labelName: any) {
await expandCategory(categoryName); await expandCategory(categoryName);
await clickOn(`${categoryName}:${labelName}:see-actions`); await clickOn(`${categoryName}:${labelName}:see-actions`);
await clickOn(`${categoryName}:${labelName}:delete-label`); await clickOn(`${categoryName}:${labelName}:delete-label`);
} }
export async function renameLabel(categoryName, oldLabelName, newLabelName) { export async function renameLabel(
categoryName: any,
oldLabelName: any,
newLabelName: any
) {
await expandCategory(categoryName); await expandCategory(categoryName);
await clickOn(`${categoryName}:${oldLabelName}:see-actions`); await clickOn(`${categoryName}:${oldLabelName}:see-actions`);
await clickOn(`${categoryName}:${oldLabelName}:edit-label`); await clickOn(`${categoryName}:${oldLabelName}:edit-label`);
@@ -397,13 +430,13 @@ export async function renameLabel(categoryName, oldLabelName, newLabelName) {
await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`); await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`);
} }
export async function addGeneToSearch(geneName) { export async function addGeneToSearch(geneName: any) {
await typeInto("gene-search", geneName); await typeInto("gene-search", geneName);
await page.keyboard.press("Enter"); await page.keyboard.press("Enter");
await page.waitForSelector(`[data-testid='histogram-${geneName}']`); await page.waitForSelector(`[data-testid='histogram-${geneName}']`);
} }
export async function subset(coordinatesAsPercent) { export async function subset(coordinatesAsPercent: any) {
// In order to deselect the selection after the subset, make sure we have some clear part // In order to deselect the selection after the subset, make sure we have some clear part
// of the scatterplot we can click on // of the scatterplot we can click on
assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99); assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99);
@@ -417,8 +450,8 @@ export async function subset(coordinatesAsPercent) {
await clickOnCoordinate("layout-graph", clearCoordinate); await clickOnCoordinate("layout-graph", clearCoordinate);
} }
export async function setSellSet(cellSet, cellSetNum) { export async function setSellSet(cellSet: any, cellSetNum: any) {
const selections = cellSet.filter((sel) => sel.kind === "categorical"); const selections = cellSet.filter((sel: any) => sel.kind === "categorical");
for (const selection of selections) { for (const selection of selections) {
await selectCategory(selection.metadata, selection.values, true); await selectCategory(selection.metadata, selection.values, true);
@@ -427,19 +460,20 @@ export async function setSellSet(cellSet, cellSetNum) {
await getCellSetCount(cellSetNum); await getCellSetCount(cellSetNum);
} }
export async function runDiffExp(cellSet1, cellSet2) { export async function runDiffExp(cellSet1: any, cellSet2: any) {
await setSellSet(cellSet1, 1); await setSellSet(cellSet1, 1);
await setSellSet(cellSet2, 2); await setSellSet(cellSet2, 2);
await clickOn("diffexp-button"); await clickOn("diffexp-button");
} }
export async function bulkAddGenes(geneNames) { export async function bulkAddGenes(geneNames: any) {
await clickOn("section-bulk-add"); await clickOn("section-bulk-add");
await typeInto("input-bulk-add", geneNames.join(",")); await typeInto("input-bulk-add", geneNames.join(","));
await page.keyboard.press("Enter"); await page.keyboard.press("Enter");
} }
export async function assertCategoryDoesNotExist(categoryName) { export async function assertCategoryDoesNotExist(categoryName: any) {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const result = await isElementPresent( const result = await isElementPresent(
getTestId(`${categoryName}:category-label`) getTestId(`${categoryName}:category-label`)
); );
@@ -480,7 +514,7 @@ export async function logout() {
await waitByID("log-in"); await waitByID("log-in");
} }
async function waitUntilFormFieldStable(selector) { async function waitUntilFormFieldStable(selector: any) {
const MAX_RETRY = 10; const MAX_RETRY = 10;
const WAIT_FOR_MS = 200; const WAIT_FOR_MS = 200;
@@ -58,10 +58,12 @@ describe("metadata loads", () => {
const categories = await getAllCategoriesAndCounts(label); const categories = await getAllCategoriesAndCounts(label);
expect(Object.keys(categories)).toMatchObject( expect(Object.keys(categories)).toMatchObject(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
Object.keys(data.categorical[label]) Object.keys(data.categorical[label])
); );
expect(Object.values(categories)).toMatchObject( expect(Object.values(categories)).toMatchObject(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
Object.values(data.categorical[label]) Object.values(data.categorical[label])
); );
} }
@@ -159,10 +161,12 @@ describe("subset", () => {
const categories = await getAllCategoriesAndCounts(label); const categories = await getAllCategoriesAndCounts(label);
expect(Object.keys(categories)).toMatchObject( expect(Object.keys(categories)).toMatchObject(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
Object.keys(data.subset.categorical[label]) Object.keys(data.subset.categorical[label])
); );
expect(Object.values(categories)).toMatchObject( expect(Object.values(categories)).toMatchObject(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
Object.values(data.subset.categorical[label]) Object.values(data.subset.categorical[label])
); );
} }
@@ -195,6 +199,7 @@ describe("clipping", () => {
test("clip continuous", async () => { test("clip continuous", async () => {
await goToPage(appUrlBase); await goToPage(appUrlBase);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string' is not assignable to par... Remove this comment to see the full error message
await clip(data.clip.min, data.clip.max); await clip(data.clip.min, data.clip.max);
const histBrushableAreaId = `histogram-${data.clip.metadata}-plot-brushable-area`; const histBrushableAreaId = `histogram-${data.clip.metadata}-plot-brushable-area`;
const coords = await calcDragCoordinates( const coords = await calcDragCoordinates(
@@ -254,6 +259,7 @@ describe("centroid labels", () => {
const generatedLabels = await getAllByClass("centroid-label"); const generatedLabels = await getAllByClass("centroid-label");
// Number of labels generated should be equal to size of the object // Number of labels generated should be equal to size of the object
expect(generatedLabels).toHaveLength( expect(generatedLabels).toHaveLength(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
Object.keys(data.categorical[label]).length Object.keys(data.categorical[label]).length
); );
} }
@@ -275,6 +281,7 @@ describe("graph overlay", () => {
data.pan["coordinates-as-percent"] data.pan["coordinates-as-percent"]
); );
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const categoryValue = Object.keys(data.categorical[category])[0]; const categoryValue = Object.keys(data.categorical[category])[0];
const initialCoordinates = await getElementCoordinates( const initialCoordinates = await getElementCoordinates(
`${categoryValue}-centroid-label` `${categoryValue}-centroid-label`
@@ -76,7 +76,7 @@ const brushThisGeneGeneset = "brush_this_gene";
const geneBrushedCellCount = "109"; const geneBrushedCellCount = "109";
const subsetGeneBrushedCellCount = "96"; const subsetGeneBrushedCellCount = "96";
async function setup(config) { async function setup(config: any) {
await goToPage(appUrlBase); await goToPage(appUrlBase);
if (config.categoricalAnno) { if (config.categoricalAnno) {
@@ -150,7 +150,7 @@ describe.each([
await expect(page).toClick(getTestClass("pop-1-geneset-expand")); await expect(page).toClick(getTestClass("pop-1-geneset-expand"));
await page.waitForFunction( await page.waitForFunction(
(selector) => !document.querySelector(selector), (selector: any) => !document.querySelector(selector),
{}, {},
getTestClass("gene-loading-spinner") getTestClass("gene-loading-spinner")
); );
@@ -165,7 +165,7 @@ describe.each([
await expect(page).toClick(getTestClass("pop-2-geneset-expand")); await expect(page).toClick(getTestClass("pop-2-geneset-expand"));
await page.waitForFunction( await page.waitForFunction(
(selector) => !document.querySelector(selector), (selector: any) => !document.querySelector(selector),
{}, {},
getTestClass("gene-loading-spinner") getTestClass("gene-loading-spinner")
); );
@@ -362,8 +362,11 @@ describe.each([
expect(actualLabelName).toBe(expectedLabelName); expect(actualLabelName).toBe(expectedLabelName);
expect(actualLabelCount).toBe(expectedLabelCount); expect(actualLabelCount).toBe(expectedLabelCount);
async function getInnerText(element, className) { async function getInnerText(element: any, className: any) {
return element.$eval(getTestClass(className), (node) => node?.innerText); return element.$eval(
getTestClass(className),
(node: any) => node?.innerText
);
} }
}); });
@@ -388,7 +391,9 @@ describe.each([
`categorical-value-count-${perTestCategoryName}-${perTestLabelName}` `categorical-value-count-${perTestCategoryName}-${perTestLabelName}`
); );
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
expect(await result.evaluate((node) => node.innerText)).toBe( expect(await result.evaluate((node) => node.innerText)).toBe(
// @ts-expect-error ts-migrate(2538) FIXME: Type 'boolean' cannot be used as an index type.
data.categoryLabel.newCount.bySubsetConfig[config.withSubset] data.categoryLabel.newCount.bySubsetConfig[config.withSubset]
); );
}); });
@@ -448,6 +453,7 @@ describe.each([
await createLabel(perTestCategoryName, labelName); await createLabel(perTestCategoryName, labelName);
await assertLabelExists(perTestCategoryName, labelName); await assertLabelExists(perTestCategoryName, labelName);
await clickOn("undo"); await clickOn("undo");
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
await assertLabelDoesNotExist(perTestCategoryName); await assertLabelDoesNotExist(perTestCategoryName);
await clickOn("redo"); await clickOn("redo");
await assertLabelExists(perTestCategoryName, labelName); await assertLabelExists(perTestCategoryName, labelName);
@@ -457,10 +463,12 @@ describe.each([
await setup(config); await setup(config);
await deleteLabel(perTestCategoryName, perTestLabelName); await deleteLabel(perTestCategoryName, perTestLabelName);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
await assertLabelDoesNotExist(perTestCategoryName); await assertLabelDoesNotExist(perTestCategoryName);
await clickOn("undo"); await clickOn("undo");
await assertLabelExists(perTestCategoryName, perTestLabelName); await assertLabelExists(perTestCategoryName, perTestLabelName);
await clickOn("redo"); await clickOn("redo");
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
await assertLabelDoesNotExist(perTestCategoryName); await assertLabelDoesNotExist(perTestCategoryName);
}); });
@@ -523,9 +531,10 @@ describe.each([
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
async function assertCategoryExists(categoryName) { async function assertCategoryExists(categoryName: any) {
const handle = await waitByID(`${categoryName}:category-label`); const handle = await waitByID(`${categoryName}:category-label`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const result = await handle.evaluate((node) => const result = await handle.evaluate((node) =>
node.getAttribute("aria-label") node.getAttribute("aria-label")
); );
@@ -533,7 +542,7 @@ describe.each([
return expect(result).toBe(categoryName); return expect(result).toBe(categoryName);
} }
async function assertLabelExists(categoryName, labelName) { async function assertLabelExists(categoryName: any, labelName: any) {
await expect(page).toMatchElement( await expect(page).toMatchElement(
getTestId(`${categoryName}:category-expand`) getTestId(`${categoryName}:category-expand`)
); );
@@ -545,11 +554,12 @@ describe.each([
); );
expect( expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
await previous.evaluate((node) => node.getAttribute("aria-label")) await previous.evaluate((node) => node.getAttribute("aria-label"))
).toBe(labelName); ).toBe(labelName);
} }
async function assertLabelDoesNotExist(categoryName, labelName) { async function assertLabelDoesNotExist(categoryName: any, labelName: any) {
await expandCategory(categoryName); await expandCategory(categoryName);
const result = await page.$( const result = await page.$(
`[data-testid='categorical-value-${categoryName}-${labelName}']` `[data-testid='categorical-value-${categoryName}-${labelName}']`
+4 -4
View File
@@ -1,10 +1,10 @@
{ {
"testRunner": "jest-circus/runner", "testRunner": "jest-circus/runner",
"preset": "jest-puppeteer", "preset": "jest-puppeteer",
"testMatch": ["**/__tests__/**/?(*.)(spec|test).js?(x)"], "testMatch": ["**/__tests__/**/?(*.)(spec|test).ts?(x)"],
"setupFiles": ["../setupMissingGlobals.js"], "setupFiles": ["../setupMissingGlobals.ts"],
"setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.js"], "setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.ts"],
"globalSetup": "../globalSetup.js", "globalSetup": "../globalSetup.ts",
"globalTeardown": "jest-environment-puppeteer/teardown", "globalTeardown": "jest-environment-puppeteer/teardown",
"testEnvironment": "./screenshot_env.js" "testEnvironment": "./screenshot_env.js"
} }
@@ -23,6 +23,7 @@ beforeEach(async () => {
const userAgent = await browser.userAgent(); const userAgent = await browser.userAgent();
await page.setUserAgent(`${userAgent}bot`); await page.setUserAgent(`${userAgent}bot`);
// @ts-expect-error ts-migrate(2341) FIXME: Property '_client' is private and only accessible ... Remove this comment to see the full error message
await page._client.send("Animation.setPlaybackRate", { playbackRate: 12 }); await page._client.send("Animation.setPlaybackRate", { playbackRate: 12 });
page.on("pageerror", (err) => { page.on("pageerror", (err) => {
@@ -49,7 +50,7 @@ beforeEach(async () => {
} }
const errorMsgText = await Promise.all( const errorMsgText = await Promise.all(
// TODO can we do this without internal properties? // TODO can we do this without internal properties?
msg.args().map((arg) => arg._remoteObject.description) msg.args().map((arg: any) => arg._remoteObject.description)
); );
throw new Error(`Console error: ${errorMsgText}`); throw new Error(`Console error: ${errorMsgText}`);
} }
@@ -1,31 +1,31 @@
/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ /* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
export function getTestId(id) { export function getTestId(id: any) {
return `[data-testid='${id}']`; return `[data-testid='${id}']`;
} }
export function getTestClass(className) { export function getTestClass(className: any) {
return `[data-testclass='${className}']`; return `[data-testclass='${className}']`;
} }
export async function waitByID(testId, props = {}) { export async function waitByID(testId: any, props = {}) {
return page.waitForSelector(getTestId(testId), props); return page.waitForSelector(getTestId(testId), props);
} }
export async function waitByClass(testClass, props = {}) { export async function waitByClass(testClass: any, props = {}) {
return page.waitForSelector(`[data-testclass='${testClass}']`, props); return page.waitForSelector(`[data-testclass='${testClass}']`, props);
} }
export async function waitForAllByIds(testIds) { export async function waitForAllByIds(testIds: any) {
await Promise.all( await Promise.all(
testIds.map((testId) => page.waitForSelector(getTestId(testId))) testIds.map((testId: any) => page.waitForSelector(getTestId(testId)))
); );
} }
export async function getAllByClass(testClass) { export async function getAllByClass(testClass: any) {
return page.$$(`[data-testclass=${testClass}]`); return page.$$(`[data-testclass=${testClass}]`);
} }
export async function typeInto(testId, text) { export async function typeInto(testId: any, text: any) {
// blueprint's typeahead is treating typing weird, clicking & waiting first solves this // blueprint's typeahead is treating typing weird, clicking & waiting first solves this
// only works for text without special characters // only works for text without special characters
await waitByID(testId); await waitByID(testId);
@@ -36,7 +36,7 @@ export async function typeInto(testId, text) {
await page.type(selector, text); await page.type(selector, text);
} }
export async function clearInputAndTypeInto(testId, text) { export async function clearInputAndTypeInto(testId: any, text: any) {
await waitByID(testId); await waitByID(testId);
const selector = getTestId(testId); const selector = getTestId(testId);
// only works for text without special characters // only works for text without special characters
@@ -49,7 +49,7 @@ export async function clearInputAndTypeInto(testId, text) {
await page.type(selector, text); await page.type(selector, text);
} }
export async function clickOn(testId, options = {}) { export async function clickOn(testId: any, options = {}) {
await expect(page).toClick(getTestId(testId), options); await expect(page).toClick(getTestId(testId), options);
} }
@@ -57,7 +57,7 @@ export async function clickOn(testId, options = {}) {
* (thuang): There are times when Puppeteer clicks on a button and the page doesn't respond. * (thuang): There are times when Puppeteer clicks on a button and the page doesn't respond.
* So I added clickOnUntil() to retry clicking until a given condition is met. * So I added clickOnUntil() to retry clicking until a given condition is met.
*/ */
export async function clickOnUntil(testId, assert) { export async function clickOnUntil(testId: any, assert: any) {
const MAX_RETRY = 10; const MAX_RETRY = 10;
const WAIT_FOR_MS = 200; const WAIT_FOR_MS = 200;
@@ -81,19 +81,19 @@ export async function clickOnUntil(testId, assert) {
} }
} }
export async function getOneElementInnerHTML(selector, options = {}) { export async function getOneElementInnerHTML(selector: any, options = {}) {
await page.waitForSelector(selector, options); await page.waitForSelector(selector, options);
return page.$eval(selector, (el) => el.innerHTML); return page.$eval(selector, (el) => el.innerHTML);
} }
export async function getOneElementInnerText(selector) { export async function getOneElementInnerText(selector: any) {
expect(page).toMatchElement(selector); expect(page).toMatchElement(selector);
return page.$eval(selector, (el) => el.innerText); return page.$eval(selector, (el) => (el as any).innerText);
} }
export async function getElementCoordinates(testId) { export async function getElementCoordinates(testId: any) {
return page.$eval(getTestId(testId), (elem) => { return page.$eval(getTestId(testId), (elem) => {
const { left, top } = elem.getBoundingClientRect(); const { left, top } = elem.getBoundingClientRect();
return [left, top]; return [left, top];
@@ -101,12 +101,14 @@ export async function getElementCoordinates(testId) {
} }
async function clickTermsOfService() { async function clickTermsOfService() {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return; if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return;
await clickOn("tos-cookies-accept"); await clickOn("tos-cookies-accept");
} }
async function nameNewAnnotation() { async function nameNewAnnotation() {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
if (await isElementPresent(getTestId("annotation-dialog"))) { if (await isElementPresent(getTestId("annotation-dialog"))) {
await typeInto("new-annotation-name", "ignoreE2E"); await typeInto("new-annotation-name", "ignoreE2E");
await clickOn("submit-annotation"); await clickOn("submit-annotation");
@@ -116,7 +118,7 @@ async function nameNewAnnotation() {
} }
} }
export async function goToPage(url) { export async function goToPage(url: any) {
await page.goto(url, { await page.goto(url, {
waitUntil: "networkidle0", waitUntil: "networkidle0",
}); });
@@ -125,7 +127,8 @@ export async function goToPage(url) {
await clickTermsOfService(); await clickTermsOfService();
} }
export async function isElementPresent(selector, options) { export async function isElementPresent(selector: any, options: any) {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
return Boolean(await page.$(selector, options)); return Boolean(await page.$(selector, options));
} }
/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ /* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
+1
View File
@@ -2,6 +2,7 @@ const PuppeteerEnvironment = require("jest-environment-puppeteer");
require("jest-circus"); require("jest-circus");
const ENV_DEFAULT = require("../../../environment.default.json"); const ENV_DEFAULT = require("../../../environment.default.json");
// @ts-expect-error ts-migrate(2451) FIXME: Cannot redeclare block-scoped variable 'takeScreen... Remove this comment to see the full error message
const takeScreenshot = require("./takeScreenshot"); const takeScreenshot = require("./takeScreenshot");
class ScreenshotEnvironment extends PuppeteerEnvironment { class ScreenshotEnvironment extends PuppeteerEnvironment {
@@ -1,3 +1,4 @@
// @ts-ignore FIXME revisit from ts-migrate
const { const {
SecretsManagerClient, SecretsManagerClient,
GetSecretValueCommand, GetSecretValueCommand,
@@ -20,7 +20,12 @@ describe("cascade", () => {
const reducer = cascadeReducers([ const reducer = cascadeReducers([
[ [
"foo", "foo",
(currentState, action, nextSharedState, prevSharedState) => { (
currentState: any,
action: any,
nextSharedState: any,
prevSharedState: any
) => {
expect(currentState).toBeUndefined(); expect(currentState).toBeUndefined();
expect(action).toEqual(topLevelAction); expect(action).toEqual(topLevelAction);
expect(nextSharedState).toStrictEqual({}); expect(nextSharedState).toStrictEqual({});
@@ -30,7 +35,12 @@ describe("cascade", () => {
], ],
[ [
"bar", "bar",
(currentState, action, nextSharedState, prevSharedState) => { (
currentState: any,
action: any,
nextSharedState: any,
prevSharedState: any
) => {
expect(currentState).toBeUndefined(); expect(currentState).toBeUndefined();
expect(action).toEqual(topLevelAction); expect(action).toEqual(topLevelAction);
expect(nextSharedState).toStrictEqual({ foo: 0 }); expect(nextSharedState).toStrictEqual({ foo: 0 });
@@ -501,6 +501,7 @@ describe("geneset: set tid", () => {
test("not a number error", () => { test("not a number error", () => {
expect(() => { expect(() => {
genesetsReducer( genesetsReducer(
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number' is not assignable to type 'undefined... Remove this comment to see the full error message
{ lastTid: 1 }, { lastTid: 1 },
{ {
type: "geneset: set tid", type: "geneset: set tid",
@@ -513,6 +514,7 @@ describe("geneset: set tid", () => {
test("decrement error", () => { test("decrement error", () => {
expect(() => { expect(() => {
genesetsReducer( genesetsReducer(
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number' is not assignable to type 'undefined... Remove this comment to see the full error message
{ lastTid: 1 }, { lastTid: 1 },
{ {
type: "geneset: set tid", type: "geneset: set tid",
@@ -2,6 +2,7 @@ import undoable from "../../src/reducers/undoable";
describe("create", () => { describe("create", () => {
test("no keys", () => { test("no keys", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2-3 arguments, but got 1.
expect(() => undoable(() => {})).toThrow(); expect(() => undoable(() => {})).toThrow();
expect(() => undoable(() => {}, null)).toThrow(); expect(() => undoable(() => {}, null)).toThrow();
expect(() => undoable(() => {}, [])).toThrow(); expect(() => undoable(() => {}, [])).toThrow();
@@ -23,7 +24,7 @@ describe("create", () => {
describe("undo", () => { describe("undo", () => {
test("expected state modifications", () => { test("expected state modifications", () => {
const initialState = { a: 0, b: 1000 }; const initialState = { a: 0, b: 1000 };
const reducer = (state) => { const reducer = (state: any) => {
return { a: state.a + 1, b: state.b + 1 }; return { a: state.a + 1, b: state.b + 1 };
}; };
const undoableReducer = undoable(reducer, ["a"]); const undoableReducer = undoable(reducer, ["a"]);
@@ -43,10 +44,10 @@ describe("undo", () => {
describe("redo", () => { describe("redo", () => {
const initialState = { a: 0, b: 1000 }; const initialState = { a: 0, b: 1000 };
const reducer = (state) => { const reducer = (state: any) => {
return { a: state.a + 1, b: state.b + 1 }; return { a: state.a + 1, b: state.b + 1 };
}; };
let UR; let UR: any;
beforeEach(() => { beforeEach(() => {
UR = undoable(reducer, ["a"]); UR = undoable(reducer, ["a"]);
@@ -5,5 +5,6 @@ the jest test environment).
import { TextDecoder, TextEncoder } from "util"; import { TextDecoder, TextEncoder } from "util";
// @ts-expect-error ts-migrate(2322) FIXME: Type 'typeof TextDecoder' is not assignable to typ... Remove this comment to see the full error message
global.TextDecoder = TextDecoder; global.TextDecoder = TextDecoder;
global.TextEncoder = TextEncoder; global.TextEncoder = TextEncoder;
@@ -14,10 +14,11 @@ import { Dataframe } from "../../../src/util/dataframe";
enableFetchMocks(); enableFetchMocks();
describe("AnnoMatrix", () => { describe("AnnoMatrix", () => {
let annoMatrix; let annoMatrix: any;
beforeEach(async () => { beforeEach(async () => {
fetch.resetMocks(); // reset all fetch mocking state (fetch as any).resetMocks(); // reset all fetch mocking state
// reset all fetch mocking state
annoMatrix = new AnnoMatrixLoader( annoMatrix = new AnnoMatrixLoader(
serverMocks.baseDataURL, serverMocks.baseDataURL,
serverMocks.schema.schema serverMocks.schema.schema
@@ -36,7 +37,7 @@ describe("AnnoMatrix", () => {
}); });
test("simple single column fetch", async () => { test("simple single column fetch", async () => {
fetch.once(serverMocks.annotationsObs(["name_0"])); (fetch as any).once(serverMocks.annotationsObs(["name_0"]));
const df = await annoMatrix.fetch("obs", "name_0"); const df = await annoMatrix.fetch("obs", "name_0");
expect(df).toBeInstanceOf(Dataframe); expect(df).toBeInstanceOf(Dataframe);
@@ -45,7 +46,7 @@ describe("AnnoMatrix", () => {
}); });
test("simple multi column fetch", async () => { test("simple multi column fetch", async () => {
fetch (fetch as any)
.once(serverMocks.annotationsObs(["name_0"])) .once(serverMocks.annotationsObs(["name_0"]))
.once(serverMocks.annotationsObs(["n_genes"])); .once(serverMocks.annotationsObs(["n_genes"]));
@@ -55,9 +56,11 @@ describe("AnnoMatrix", () => {
}); });
describe("fetch from field", () => { describe("fetch from field", () => {
const getLastTwo = async (field) => { const getLastTwo = async (field: any) => {
const columnNames = annoMatrix.getMatrixColumns(field).slice(-2); const columnNames = annoMatrix.getMatrixColumns(field).slice(-2);
fetch.mockResponses(...columnNames.map(() => serverMocks.responder)); (fetch as any).mockResponses(
...columnNames.map(() => serverMocks.responder)
);
await expect( await expect(
annoMatrix.fetch(field, columnNames) annoMatrix.fetch(field, columnNames)
).resolves.toBeInstanceOf(Dataframe); ).resolves.toBeInstanceOf(Dataframe);
@@ -70,19 +73,19 @@ describe("AnnoMatrix", () => {
test("fetch - test all query forms", async () => { test("fetch - test all query forms", async () => {
// single string is a column name // single string is a column name
fetch.once(serverMocks.annotationsObs(["n_genes"])); (fetch as any).once(serverMocks.annotationsObs(["n_genes"]));
await expect(annoMatrix.fetch("obs", "n_genes")).resolves.toBeInstanceOf( await expect(annoMatrix.fetch("obs", "n_genes")).resolves.toBeInstanceOf(
Dataframe Dataframe
); );
// array of column names, expecting n_genes to be cached. // array of column names, expecting n_genes to be cached.
fetch.once(serverMocks.annotationsObs(["percent_mito"])); (fetch as any).once(serverMocks.annotationsObs(["percent_mito"]));
await expect( await expect(
annoMatrix.fetch("obs", ["n_genes", "percent_mito"]) annoMatrix.fetch("obs", ["n_genes", "percent_mito"])
).resolves.toBeInstanceOf(Dataframe); ).resolves.toBeInstanceOf(Dataframe);
// more complex value filter query, enumerated // more complex value filter query, enumerated
fetch.once(serverMocks.responder); (fetch as any).once(serverMocks.responder);
await expect( await expect(
annoMatrix.fetch("X", { annoMatrix.fetch("X", {
where: { where: {
@@ -95,7 +98,7 @@ describe("AnnoMatrix", () => {
// more complex value filter query, range // more complex value filter query, range
const varIndex = annoMatrix.schema.annotations.var.index; const varIndex = annoMatrix.schema.annotations.var.index;
fetch (fetch as any)
.once( .once(
serverMocks.withExpected("/data/var", [[`var:${varIndex}`, "SUMO3"]]) serverMocks.withExpected("/data/var", [[`var:${varIndex}`, "SUMO3"]])
) )
@@ -171,7 +174,7 @@ describe("AnnoMatrix", () => {
expect(am1.nObs).toEqual(am2.nObs); expect(am1.nObs).toEqual(am2.nObs);
expect(am1.nVar).toEqual(am2.nVar); expect(am1.nVar).toEqual(am2.nVar);
fetch (fetch as any)
.once(serverMocks.annotationsObs(["n_genes"])) .once(serverMocks.annotationsObs(["n_genes"]))
.once(serverMocks.annotationsObs(["n_genes"])); .once(serverMocks.annotationsObs(["n_genes"]));
const ng1 = await am1.fetch("obs", "n_genes"); const ng1 = await am1.fetch("obs", "n_genes");
@@ -185,9 +188,10 @@ describe("AnnoMatrix", () => {
}); });
describe("add/drop column", () => { describe("add/drop column", () => {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type.
async function addDrop(base) { async function addDrop(base) {
expect(base.getMatrixColumns("obs")).not.toContain("foo"); expect(base.getMatrixColumns("obs")).not.toContain("foo");
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(base.fetch("obs", "foo")).rejects.toThrow( await expect(base.fetch("obs", "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -212,7 +216,7 @@ describe("AnnoMatrix", () => {
const am2 = am1.dropObsColumn("foo"); const am2 = am1.dropObsColumn("foo");
expect(base.getMatrixColumns("obs")).not.toContain("foo"); expect(base.getMatrixColumns("obs")).not.toContain("foo");
expect(am2.getMatrixColumns("obs")).not.toContain("foo"); expect(am2.getMatrixColumns("obs")).not.toContain("foo");
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(am2.fetch("obs", "foo")).rejects.toThrow( await expect(am2.fetch("obs", "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -235,14 +239,14 @@ describe("AnnoMatrix", () => {
const am4 = clip(am3, 0, 1); const am4 = clip(am3, 0, 1);
await addDrop(am4); await addDrop(am4);
fetch.mockResponse(serverMocks.responder); (fetch as any).mockResponse(serverMocks.responder);
await am1.fetch("obs", am1.getMatrixColumns("obs")); await am1.fetch("obs", am1.getMatrixColumns("obs"));
await am2.fetch("obs", am2.getMatrixColumns("obs")); await am2.fetch("obs", am2.getMatrixColumns("obs"));
await am3.fetch("obs", am3.getMatrixColumns("obs")); await am3.fetch("obs", am3.getMatrixColumns("obs"));
await am4.fetch("obs", am4.getMatrixColumns("obs")); await am4.fetch("obs", am4.getMatrixColumns("obs"));
fetch.resetMocks(); (fetch as any).resetMocks();
await addDrop(am1); await addDrop(am1);
await addDrop(am2); await addDrop(am2);
@@ -252,6 +256,7 @@ describe("AnnoMatrix", () => {
}); });
describe("setObsColumnValues", () => { describe("setObsColumnValues", () => {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type.
async function addSetDrop(base) { async function addSetDrop(base) {
/* add column */ /* add column */
let am = base.addObsColumn( let am = base.addObsColumn(
@@ -287,7 +292,7 @@ describe("AnnoMatrix", () => {
); );
/* drop column */ /* drop column */
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
am = am1.dropObsColumn("test"); am = am1.dropObsColumn("test");
await expect(am.fetch("obs", "test")).rejects.toThrow( await expect(am.fetch("obs", "test")).rejects.toThrow(
"unknown column name" "unknown column name"
@@ -308,7 +313,7 @@ describe("AnnoMatrix", () => {
const am3 = isubset(annoMatrix, [10, 1, 0, 30, 2]); const am3 = isubset(annoMatrix, [10, 1, 0, 30, 2]);
await addSetDrop(am3); await addSetDrop(am3);
fetch.mockResponse(serverMocks.responder); (fetch as any).mockResponse(serverMocks.responder);
await am1.fetch("obs", am1.getMatrixColumns("obs")); await am1.fetch("obs", am1.getMatrixColumns("obs"));
await am2.fetch("obs", am2.getMatrixColumns("obs")); await am2.fetch("obs", am2.getMatrixColumns("obs"));
@@ -17,11 +17,12 @@ import { rangeFill } from "../../../src/util/range";
enableFetchMocks(); enableFetchMocks();
describe("AnnoMatrixCrossfilter", () => { describe("AnnoMatrixCrossfilter", () => {
let annoMatrix; let annoMatrix: any;
let crossfilter; let crossfilter: any;
beforeEach(async () => { beforeEach(async () => {
fetch.resetMocks(); // reset all fetch mocking state (fetch as any).resetMocks(); // reset all fetch mocking state
// reset all fetch mocking state
annoMatrix = new AnnoMatrixLoader( annoMatrix = new AnnoMatrixLoader(
serverMocks.baseDataURL, serverMocks.baseDataURL,
serverMocks.schema.schema serverMocks.schema.schema
@@ -67,7 +68,9 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.obsCrossfilter.hasDimension("obs/louvain") crossfilter.obsCrossfilter.hasDimension("obs/louvain")
).toBeFalsy(); ).toBeFalsy();
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
let newCrossfilter = await crossfilter.select("obs", "louvain", { let newCrossfilter = await crossfilter.select("obs", "louvain", {
mode: "none", mode: "none",
}); });
@@ -76,7 +79,7 @@ describe("AnnoMatrixCrossfilter", () => {
expect( expect(
newCrossfilter.obsCrossfilter.hasDimension("obs/louvain") newCrossfilter.obsCrossfilter.hasDimension("obs/louvain")
).toBeTruthy(); ).toBeTruthy();
expect(fetch.mock.calls).toHaveLength(1); expect((fetch as any).mock.calls).toHaveLength(1);
newCrossfilter = await crossfilter.select("obs", "louvain", { newCrossfilter = await crossfilter.select("obs", "louvain", {
mode: "all", mode: "all",
@@ -87,7 +90,9 @@ describe("AnnoMatrixCrossfilter", () => {
test("simple column select", async () => { test("simple column select", async () => {
let xfltr; let xfltr;
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
xfltr = await crossfilter.select("obs", "louvain", { xfltr = await crossfilter.select("obs", "louvain", {
mode: "exact", mode: "exact",
values: ["NK cells", "B cells"], values: ["NK cells", "B cells"],
@@ -105,6 +110,7 @@ describe("AnnoMatrixCrossfilter", () => {
expect(xfltr.allSelectedLabels()).toEqual( expect(xfltr.allSelectedLabels()).toEqual(
Int32Array.from( Int32Array.from(
obsLouvain.reduce((acc, val, idx) => { obsLouvain.reduce((acc, val, idx) => {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number' is not assignable to par... Remove this comment to see the full error message
if (val === "NK cells" || val === "B cells") acc.push(idx); if (val === "NK cells" || val === "B cells") acc.push(idx);
return acc; return acc;
}, []) }, [])
@@ -124,10 +130,11 @@ describe("AnnoMatrixCrossfilter", () => {
const values = df.col("louvain").asArray(); const values = df.col("louvain").asArray();
const selected = xfltr.allSelectedMask(); const selected = xfltr.allSelectedMask();
values.every( values.every(
(val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx] (val: any, idx: any) =>
!["NK cells", "B cells"].includes(val) !== !selected[idx]
); );
fetch.once( (fetch as any).once(
serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)]) serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)])
); );
xfltr = await xfltr.select("obs", "n_genes", { xfltr = await xfltr.select("obs", "n_genes", {
@@ -146,6 +153,7 @@ describe("AnnoMatrixCrossfilter", () => {
val < 500 && val < 500 &&
(louvain === "NK cells" || louvain === "B cells") (louvain === "NK cells" || louvain === "B cells")
) )
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number' is not assignable to par... Remove this comment to see the full error message
acc.push(idx); acc.push(idx);
return acc; return acc;
}, []) }, [])
@@ -160,7 +168,7 @@ describe("AnnoMatrixCrossfilter", () => {
const varIndex = annoMatrix.schema.annotations.var.index; const varIndex = annoMatrix.schema.annotations.var.index;
const { nObs } = annoMatrix.schema.dataframe; const { nObs } = annoMatrix.schema.dataframe;
fetch.once( (fetch as any).once(
serverMocks.dataframeResponse( serverMocks.dataframeResponse(
["TEST"], ["TEST"],
[rangeFill(new Float32Array(nObs), 0, 0.1)] [rangeFill(new Float32Array(nObs), 0, 0.1)]
@@ -196,14 +204,16 @@ describe("AnnoMatrixCrossfilter", () => {
}); });
const values = df.icol(0).asArray(); const values = df.icol(0).asArray();
const selected = xfltr.allSelectedMask(); const selected = xfltr.allSelectedMask();
values.every((val, idx) => !(val >= 0 && val <= 50) !== !selected[idx]); values.every(
expect(selected.reduce((acc, val) => (val ? acc + 1 : acc), 0)).toEqual( (val: any, idx: any) => !(val >= 0 && val <= 50) !== !selected[idx]
xfltr.countSelected()
); );
expect(
selected.reduce((acc: any, val: any) => (val ? acc + 1 : acc), 0)
).toEqual(xfltr.countSelected());
}); });
test("spatial column select", async () => { test("spatial column select", async () => {
fetch.once( (fetch as any).once(
serverMocks.dataframeResponse( serverMocks.dataframeResponse(
["umap_0", "umap_1"], ["umap_0", "umap_1"],
[Float32Array.from(embUmap[0]), Float32Array.from(embUmap[1])] [Float32Array.from(embUmap[0]), Float32Array.from(embUmap[1])]
@@ -222,6 +232,7 @@ describe("AnnoMatrixCrossfilter", () => {
test("select on subset", async () => { test("select on subset", async () => {
const mask = new Uint8Array(annoMatrix.nObs).fill(0); const mask = new Uint8Array(annoMatrix.nObs).fill(0);
for (let i = 0; i < mask.length; i += 2) { for (let i = 0; i < mask.length; i += 2) {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean' is not assignable to type 'number'.
mask[i] = true; mask[i] = true;
} }
const annoMatrixSubset = isubsetMask(annoMatrix, mask); const annoMatrixSubset = isubsetMask(annoMatrix, mask);
@@ -230,7 +241,9 @@ describe("AnnoMatrixCrossfilter", () => {
let xfltr = new AnnoMatrixObsCrossfilter(annoMatrixSubset); let xfltr = new AnnoMatrixObsCrossfilter(annoMatrixSubset);
expect(xfltr.countSelected()).toEqual(annoMatrixSubset.nObs); expect(xfltr.countSelected()).toEqual(annoMatrixSubset.nObs);
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
xfltr = await xfltr.select("obs", "louvain", { xfltr = await xfltr.select("obs", "louvain", {
mode: "exact", mode: "exact",
values: ["NK cells", "B cells"], values: ["NK cells", "B cells"],
@@ -243,7 +256,8 @@ describe("AnnoMatrixCrossfilter", () => {
const values = df.col("louvain").asArray(); const values = df.col("louvain").asArray();
const selected = xfltr.allSelectedMask(); const selected = xfltr.allSelectedMask();
values.every( values.every(
(val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx] (val: any, idx: any) =>
!["NK cells", "B cells"].includes(val) !== !selected[idx]
); );
}); });
@@ -256,7 +270,7 @@ describe("AnnoMatrixCrossfilter", () => {
"unable to obsSelect upon the var dimension" "unable to obsSelect upon the var dimension"
); );
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(crossfilter.select("obs", "foo")).rejects.toThrow( await expect(crossfilter.select("obs", "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -267,24 +281,27 @@ describe("AnnoMatrixCrossfilter", () => {
/* /*
test the matrix mutators via crossfilter proxy test the matrix mutators via crossfilter proxy
*/ */
async function helperAddTestCol(cf, colName, colSchema = null) { async function helperAddTestCol(cf: any, colName: any, colSchema = null) {
expect( expect(
cf.annoMatrix.getMatrixColumns("obs").includes(colName) cf.annoMatrix.getMatrixColumns("obs").includes(colName)
).toBeFalsy(); ).toBeFalsy();
if (colSchema === null) { if (colSchema === null) {
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ name: any; type: string; categories: strin... Remove this comment to see the full error message
colSchema = { colSchema = {
name: colName, name: colName,
type: "categorical", type: "categorical",
categories: ["toasty"], categories: ["toasty"],
}; };
} }
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
colSchema.name = colName; colSchema.name = colName;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const initValue = colSchema.categories[0]; const initValue = colSchema.categories[0];
const xfltr = cf.addObsColumn(colSchema, Array, initValue); const xfltr = cf.addObsColumn(colSchema, Array, initValue);
expect( expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter( xfltr.annoMatrix.schema.annotations.obs.columns.filter(
(v) => v.name === colName (v: any) => v.name === colName
) )
).toHaveLength(1); ).toHaveLength(1);
const df = await xfltr.annoMatrix.fetch("obs", colName); const df = await xfltr.annoMatrix.fetch("obs", colName);
@@ -314,7 +331,7 @@ describe("AnnoMatrixCrossfilter", () => {
}); });
expect( expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter( xfltr.annoMatrix.schema.annotations.obs.columns.filter(
(v) => v.name === "foo" (v: any) => v.name === "foo"
) )
).toHaveLength(1); ).toHaveLength(1);
@@ -324,7 +341,7 @@ describe("AnnoMatrixCrossfilter", () => {
df df
.col("foo") .col("foo")
.asArray() .asArray()
.every((v) => v === "A") .every((v: any) => v === "A")
).toBeTruthy(); ).toBeTruthy();
// check that we catch dups // check that we catch dups
@@ -361,11 +378,11 @@ describe("AnnoMatrixCrossfilter", () => {
xfltr = xfltr.dropObsColumn("foo"); xfltr = xfltr.dropObsColumn("foo");
expect( expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter( xfltr.annoMatrix.schema.annotations.obs.columns.filter(
(v) => v.name === "foo" (v: any) => v.name === "foo"
) )
).toHaveLength(0); ).toHaveLength(0);
expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined(); expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined();
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -378,7 +395,7 @@ describe("AnnoMatrixCrossfilter", () => {
}); });
xfltr = xfltr.dropObsColumn("bar"); xfltr = xfltr.dropObsColumn("bar");
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow( await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -404,7 +421,7 @@ describe("AnnoMatrixCrossfilter", () => {
type: "categorical", type: "categorical",
}); });
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -419,7 +436,7 @@ describe("AnnoMatrixCrossfilter", () => {
}); });
xfltr = xfltr.renameObsColumn("bar", "xyz"); xfltr = xfltr.renameObsColumn("bar", "xyz");
fetch.mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow( await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -429,7 +446,7 @@ describe("AnnoMatrixCrossfilter", () => {
}); });
test("addObsAnnoCategory", async () => { test("addObsAnnoCategory", async () => {
let xfltr; let xfltr: any;
// catch unknown or readonly columns // catch unknown or readonly columns
expect(() => crossfilter.addObsAnnoCategory("louvain", "mumble")).toThrow( expect(() => crossfilter.addObsAnnoCategory("louvain", "mumble")).toThrow(
@@ -440,6 +457,7 @@ describe("AnnoMatrixCrossfilter", () => {
).toThrow("Unknown or readonly obs column"); ).toThrow("Unknown or readonly obs column");
// add a column and then add category to it // add a column and then add category to it
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "foo", { xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo", name: "foo",
type: "categorical", type: "categorical",
@@ -458,6 +476,7 @@ describe("AnnoMatrixCrossfilter", () => {
); );
// now same, but ensure we have built an index before doing the operation // now same, but ensure we have built an index before doing the operation
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "bar", { xfltr = await helperAddTestCol(crossfilter, "bar", {
name: "bar", name: "bar",
type: "categorical", type: "categorical",
@@ -486,6 +505,7 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.removeObsAnnoCategory("undefined-name", "mumble") crossfilter.removeObsAnnoCategory("undefined-name", "mumble")
).rejects.toThrow("Unknown or readonly obs column"); ).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "foo", { xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo", name: "foo",
type: "categorical", type: "categorical",
@@ -496,7 +516,7 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr.annoMatrix.fetch("obs", "foo")) (await xfltr.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.every((v) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo", name: "foo",
@@ -515,7 +535,7 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.every((v) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo", name: "foo",
@@ -538,7 +558,7 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr2.annoMatrix.fetch("obs", "foo")) (await xfltr2.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.every((v) => v === "red") .every((v: any) => v === "red")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr2.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr2.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo", name: "foo",
@@ -556,6 +576,7 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.setObsColumnValues("undefined-name", [0], "mumble") crossfilter.setObsColumnValues("undefined-name", [0], "mumble")
).rejects.toThrow("Unknown or readonly obs column"); ).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
let xfltr = await helperAddTestCol(crossfilter, "foo", { let xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo", name: "foo",
type: "categorical", type: "categorical",
@@ -573,7 +594,7 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr.annoMatrix.fetch("obs", "foo")) (await xfltr.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.every((v) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple"); const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple");
expect( expect(
@@ -581,7 +602,7 @@ describe("AnnoMatrixCrossfilter", () => {
.col("foo") .col("foo")
.asArray() .asArray()
.every( .every(
(v, i) => (v: any, i: any) =>
v === "unassigned" || (v === "purple" && (i === 0 || i === 10)) v === "unassigned" || (v === "purple" && (i === 0 || i === 10))
) )
).toBeTruthy(); ).toBeTruthy();
@@ -615,6 +636,7 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.resetObsColumnValues("undefined-name", "red", "blue") crossfilter.resetObsColumnValues("undefined-name", "red", "blue")
).rejects.toThrow("Unknown or readonly obs column"); ).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
let xfltr = await helperAddTestCol(crossfilter, "foo", { let xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo", name: "foo",
type: "categorical", type: "categorical",
@@ -639,7 +661,7 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.filter((v) => v === "purple") .filter((v: any) => v === "purple")
).toHaveLength(2); ).toHaveLength(2);
xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta"); xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta");
@@ -647,13 +669,13 @@ describe("AnnoMatrixCrossfilter", () => {
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.filter((v) => v === "magenta") .filter((v: any) => v === "magenta")
).toHaveLength(2); ).toHaveLength(2);
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.filter((v) => v === "purple") .filter((v: any) => v === "purple")
).toHaveLength(0); ).toHaveLength(0);
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo", name: "foo",
@@ -673,12 +695,14 @@ describe("AnnoMatrixCrossfilter", () => {
describe("edge cases", () => { describe("edge cases", () => {
test("transition from empty annoMatrix", async () => { test("transition from empty annoMatrix", async () => {
// select before fetch needs to work // select before fetch needs to work
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
const xfltr = await crossfilter.select("obs", "louvain", { const xfltr = await crossfilter.select("obs", "louvain", {
mode: "exact", mode: "exact",
values: "B cells", values: "B cells",
}); });
expect(fetch.mock.calls).toHaveLength(1); expect((fetch as any).mock.calls).toHaveLength(1);
expect(xfltr.obsCrossfilter.hasDimension("obs/louvain")).toBeTruthy(); expect(xfltr.obsCrossfilter.hasDimension("obs/louvain")).toBeTruthy();
expect(xfltr.obsCrossfilter.all()).toBe(xfltr.annoMatrix._cache.obs); expect(xfltr.obsCrossfilter.all()).toBe(xfltr.annoMatrix._cache.obs);
expect(xfltr.countSelected()).toEqual( expect(xfltr.countSelected()).toEqual(
@@ -1,6 +1,6 @@
export const baseDataURL = "https://a.fake.url/api/v0.2"; export const baseDataURL = "https://a.fake.url/api/v0.2";
window.CELLXGENE = { (window as any).CELLXGENE = {
API: { API: {
prefix: baseDataURL, prefix: baseDataURL,
version: "v0.2/", version: "v0.2/",
@@ -14,7 +14,7 @@ const indexedSchema = {
), ),
}; };
function makeMockColumn(s, length) { function makeMockColumn(s: any, length: any) {
const { type } = s; const { type } = s;
switch (type) { switch (type) {
case "int32": case "int32":
@@ -37,20 +37,22 @@ function makeMockColumn(s, length) {
} }
} }
function getEncodedDataframe(colNames, length, colSchemas) { function getEncodedDataframe(colNames: any, length: any, colSchemas: any) {
const colIndex = new KeyIndex(colNames); const colIndex = new KeyIndex(colNames);
const columns = colSchemas.map((s) => makeMockColumn(s, length)); const columns = colSchemas.map((s: any) => makeMockColumn(s, length));
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
const df = new Dataframe([length, colNames.length], columns, null, colIndex); const df = new Dataframe([length, colNames.length], columns, null, colIndex);
const body = encodeMatrixFBS(df); const body = encodeMatrixFBS(df);
return body; return body;
} }
export function dataframeResponse(colNames, columns) { export function dataframeResponse(colNames: any, columns: any) {
const colIndex = new KeyIndex(colNames); const colIndex = new KeyIndex(colNames);
const df = new Dataframe( const df = new Dataframe(
[columns[0].length, colNames.length], [columns[0].length, colNames.length],
columns, columns,
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
colIndex colIndex
); );
const body = encodeMatrixFBS(df); const body = encodeMatrixFBS(df);
@@ -60,15 +62,19 @@ export function dataframeResponse(colNames, columns) {
return () => Promise.resolve({ body, init: { status: 200, headers } }); return () => Promise.resolve({ body, init: { status: 200, headers } });
} }
function annotationObsResponse(request) { function annotationObsResponse(request: any) {
const url = new URL(request.url); const url = new URL(request.url);
const params = Array.from(url.searchParams.entries()); const params = Array.from((url.searchParams as any).entries());
const names = params const names = params
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
.filter(([k]) => k === "annotation-name") .filter(([k]) => k === "annotation-name")
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '([, v]: [any, any]) => any' is n... Remove this comment to see the full error message
.map(([, v]) => v); .map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.obsByName[n])) { if (!names.every((n) => indexedSchema.obsByName[n])) {
return Promise.reject(new Error("bad obs annotation name in URL")); return Promise.reject(new Error("bad obs annotation name in URL"));
} }
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const colSchemas = names.map((n) => indexedSchema.obsByName[n]); const colSchemas = names.map((n) => indexedSchema.obsByName[n]);
const body = getEncodedDataframe( const body = getEncodedDataframe(
names, names,
@@ -85,15 +91,19 @@ function annotationObsResponse(request) {
}); });
} }
function annotationVarResponse(request) { function annotationVarResponse(request: any) {
const url = new URL(request.url); const url = new URL(request.url);
const params = Array.from(url.searchParams.entries()); const params = Array.from((url.searchParams as any).entries());
const names = params const names = params
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
.filter(([k]) => k === "annotation-name") .filter(([k]) => k === "annotation-name")
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '([, v]: [any, any]) => any' is n... Remove this comment to see the full error message
.map(([, v]) => v); .map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.varByName[n])) { if (!names.every((n) => indexedSchema.varByName[n])) {
return Promise.reject(new Error("bad var annotation name in URL")); return Promise.reject(new Error("bad var annotation name in URL"));
} }
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const colSchemas = names.map((n) => indexedSchema.varByName[n]); const colSchemas = names.map((n) => indexedSchema.varByName[n]);
const body = getEncodedDataframe( const body = getEncodedDataframe(
names, names,
@@ -110,15 +120,19 @@ function annotationVarResponse(request) {
}); });
} }
function layoutObsResponse(request) { function layoutObsResponse(request: any) {
const url = new URL(request.url); const url = new URL(request.url);
const params = Array.from(url.searchParams.entries()); const params = Array.from((url.searchParams as any).entries());
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
const names = params.filter(([k]) => k === "layout-name").map(([, v]) => v); const names = params.filter(([k]) => k === "layout-name").map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.embByName[n])) { if (!names.every((n) => indexedSchema.embByName[n])) {
return Promise.reject(new Error("bad layout name in URL")); return Promise.reject(new Error("bad layout name in URL"));
} }
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const dims = names.map((n) => indexedSchema.embByName[n].dims).flat(); const dims = names.map((n) => indexedSchema.embByName[n].dims).flat();
const colSchemas = names const colSchemas = names
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
.map((n) => [indexedSchema.embByName[n], indexedSchema.embByName[n]]) .map((n) => [indexedSchema.embByName[n], indexedSchema.embByName[n]])
.flat(); .flat();
const body = getEncodedDataframe( const body = getEncodedDataframe(
@@ -136,11 +150,11 @@ function layoutObsResponse(request) {
}); });
} }
function dataVarResponse(request) { function dataVarResponse(request: any) {
const url = new URL(request.url); const url = new URL(request.url);
const params = Array.from(url.searchParams.entries()); const params = Array.from((url.searchParams as any).entries());
const colNames = params.map((v) => `${v[0]}/${v[1]}`); const colNames = params.map((v) => `${(v as any)[0]}/${(v as any)[1]}`);
const colSchemas = colNames.map(() => schema.schema.dataframe); const colSchemas = colNames.map(() => schema.schema.dataframe);
const body = getEncodedDataframe( const body = getEncodedDataframe(
colNames, colNames,
@@ -157,7 +171,7 @@ function dataVarResponse(request) {
}); });
} }
export function responder(request) { export function responder(request: any) {
const url = new URL(request.url); const url = new URL(request.url);
const { pathname } = url; const { pathname } = url;
if (pathname.endsWith("/annotations/obs")) { if (pathname.endsWith("/annotations/obs")) {
@@ -175,25 +189,30 @@ export function responder(request) {
return Promise.reject(new Error("bad URL")); return Promise.reject(new Error("bad URL"));
} }
export function withExpected(expectedURL, expectedParams) { export function withExpected(expectedURL: any, expectedParams: any) {
/* /*
Do some additional error checking Do some additional error checking
*/ */
return (request) => { return (request: any) => {
// if URL is bogus, reject the promise // if URL is bogus, reject the promise
const url = new URL(request.url); const url = new URL(request.url);
if (!url.pathname.endsWith(expectedURL)) { if (!url.pathname.endsWith(expectedURL)) {
return Promise.reject(new Error("Unexpected URL!")); return Promise.reject(new Error("Unexpected URL!"));
} }
const params = Array.from(url.searchParams.entries()).sort( const params = Array.from((url.searchParams as any).entries()).sort(
(a, b) => a[0] < b[0] // @ts-expect-error ts-migrate(2345) FIXME: Argument of type '(a: unknown, b: unknown) => bool... Remove this comment to see the full error message
(a, b) => (a as any)[0] < (b as any)[0]
); );
expectedParams = expectedParams.slice().sort((a, b) => a[0] < b[0]); expectedParams = expectedParams
.slice()
.sort((a: any, b: any) => a[0] < b[0]);
if ( if (
params.length !== expectedParams.length || params.length !== expectedParams.length ||
!params.every( !params.every(
(p, i) => p[0] === expectedParams[i][0] && p[1] === expectedParams[i][1] (p, i) =>
(p as any)[0] === expectedParams[i][0] &&
(p as any)[1] === expectedParams[i][1]
) )
) { ) {
return Promise.reject(new Error("unexpected name requested in URL")); return Promise.reject(new Error("unexpected name requested in URL"));
@@ -203,9 +222,9 @@ export function withExpected(expectedURL, expectedParams) {
}; };
} }
export function annotationsObs(names) { export function annotationsObs(names: any) {
return withExpected( return withExpected(
"/annotations/obs", "/annotations/obs",
names.map((name) => ["annotation-name", name]) names.map((name: any) => ["annotation-name", name])
); );
} }
@@ -218,10 +218,15 @@ describe("whereCache", () => {
}, },
}) })
); );
expect(wc.where.field.queryField.has("queryColumn")).toEqual(true); // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
expect(wc.where.field.queryField.get("queryColumn")).toBeInstanceOf(Map); expect((wc.where as any).field.queryField.has("queryColumn")).toEqual(true);
expect( expect(
wc.where.field.queryField.get("queryColumn").has("queryValue") // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
(wc.where as any).field.queryField.get("queryColumn")
).toBeInstanceOf(Map);
expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
(wc.where as any).field.queryField.get("queryColumn").has("queryValue")
).toEqual(true); ).toEqual(true);
expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]); expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]);
}); });
@@ -8,9 +8,9 @@ import { indexEntireSchema } from "../../src/util/stateManager/schemaHelpers";
import { _normalizeCategoricalSchema } from "../../src/annoMatrix/schema"; import { _normalizeCategoricalSchema } from "../../src/annoMatrix/schema";
describe("centroid", () => { describe("centroid", () => {
let schema; let schema: any;
let obsAnnotations; let obsAnnotations: any;
let obsLayout; let obsLayout: any;
beforeAll(() => { beforeAll(() => {
schema = indexEntireSchema(cloneDeep(REST.schema.schema)); schema = indexEntireSchema(cloneDeep(REST.schema.schema));
@@ -44,7 +44,7 @@ describe("centroid", () => {
quantile([0.5], obsLayout.col("umap_1").asArray())[0], quantile([0.5], obsLayout.col("umap_1").asArray())[0],
]; ];
centroidResult.forEach((coordinate) => { centroidResult.forEach((coordinate: any) => {
expect(coordinate).toEqual(expectedResult); expect(coordinate).toEqual(expectedResult);
}); });
}); });
@@ -68,7 +68,7 @@ describe("centroid", () => {
quantile([0.5], obsLayout.col("umap_1").asArray())[0], quantile([0.5], obsLayout.col("umap_1").asArray())[0],
]; ];
centroidResult.forEach((coordinate) => { centroidResult.forEach((coordinate: any) => {
expect(coordinate).toEqual(expectedResult); expect(coordinate).toEqual(expectedResult);
}); });
}); });
@@ -29,6 +29,7 @@ describe("dataframe constructor", () => {
const df = new Dataframe.Dataframe( const df = new Dataframe.Dataframe(
[3, 2], [3, 2],
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])], [new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([2, 1, 0]), new Dataframe.DenseInt32Index([2, 1, 0]),
new Dataframe.KeyIndex(["A", "B"]) new Dataframe.KeyIndex(["A", "B"])
); );
@@ -55,6 +56,7 @@ describe("simple data access", () => {
new Float64Array([0.0, Number.NaN, Number.POSITIVE_INFINITY, 3.14159]), new Float64Array([0.0, Number.NaN, Number.POSITIVE_INFINITY, 3.14159]),
["red", "blue", "green", "nan"], ["red", "blue", "green", "nan"],
], ],
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([3, 2, 1, 0]), new Dataframe.DenseInt32Index([3, 2, 1, 0]),
new Dataframe.KeyIndex(["numbers", "colors"]) new Dataframe.KeyIndex(["numbers", "colors"])
); );
@@ -139,10 +141,12 @@ describe("dataframe subsetting", () => {
["red", "green", "blue"], ["red", "green", "blue"],
], ],
null, // identity index null, // identity index
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"]) new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
); );
test("all rows, one column", () => { test("all rows, one column", () => {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
const dfA = sourceDf.subset(null, ["colors"]); const dfA = sourceDf.subset(null, ["colors"]);
expect(dfA).toBeDefined(); expect(dfA).toBeDefined();
expect(dfA.dims).toEqual([3, 1]); expect(dfA.dims).toEqual([3, 1]);
@@ -158,6 +162,7 @@ describe("dataframe subsetting", () => {
}); });
test("all rows, two columns", () => { test("all rows, two columns", () => {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
const dfB = sourceDf.subset(null, ["float32", "colors"]); const dfB = sourceDf.subset(null, ["float32", "colors"]);
expect(dfB).toBeDefined(); expect(dfB).toBeDefined();
expect(dfB.dims).toEqual([3, 2]); expect(dfB.dims).toEqual([3, 2]);
@@ -227,6 +232,7 @@ describe("dataframe subsetting", () => {
}); });
test("two rows, two colums", () => { test("two rows, two colums", () => {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
const dfF = sourceDf.subset([0, 2], ["int32", "float32"]); const dfF = sourceDf.subset([0, 2], ["int32", "float32"]);
expect(dfF).toBeDefined(); expect(dfF).toBeDefined();
expect(dfF.dims).toEqual([2, 2]); expect(dfF.dims).toEqual([2, 2]);
@@ -236,6 +242,7 @@ describe("dataframe subsetting", () => {
expect(dfF.colIndex.labels()).toEqual(["int32", "float32"]); expect(dfF.colIndex.labels()).toEqual(["int32", "float32"]);
// reverse the row and column order // reverse the row and column order
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
const dfFr = sourceDf.subset([2, 0], ["float32", "int32"]); const dfFr = sourceDf.subset([2, 0], ["float32", "int32"]);
expect(dfFr).toBeDefined(); expect(dfFr).toBeDefined();
expect(dfFr.dims).toEqual([2, 2]); expect(dfFr.dims).toEqual([2, 2]);
@@ -248,6 +255,7 @@ describe("dataframe subsetting", () => {
test("withRowIndex", () => { test("withRowIndex", () => {
const df = sourceDf.subset( const df = sourceDf.subset(
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
["int32", "float32"], ["int32", "float32"],
new Dataframe.DenseInt32Index([3, 2, 1]) new Dataframe.DenseInt32Index([3, 2, 1])
); );
@@ -258,12 +266,15 @@ describe("dataframe subsetting", () => {
test("withRowIndex error checks", () => { test("withRowIndex error checks", () => {
expect(() => expect(() =>
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
sourceDf.subset(null, ["red"], new Dataframe.IdentityInt32Index(1)) sourceDf.subset(null, ["red"], new Dataframe.IdentityInt32Index(1))
).toThrow(RangeError); ).toThrow(RangeError);
expect(() => expect(() =>
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
sourceDf.subset(null, ["red"], new Dataframe.DenseInt32Index([0, 1])) sourceDf.subset(null, ["red"], new Dataframe.DenseInt32Index([0, 1]))
).toThrow(RangeError); ).toThrow(RangeError);
expect(() => expect(() =>
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
sourceDf.subset(null, ["red"], new Dataframe.KeyIndex([0, 1, 2, 3])) sourceDf.subset(null, ["red"], new Dataframe.KeyIndex([0, 1, 2, 3]))
).toThrow(RangeError); ).toThrow(RangeError);
}); });
@@ -278,12 +289,14 @@ describe("dataframe subsetting", () => {
new Float32Array([4.4, 5.5, 6.6]), new Float32Array([4.4, 5.5, 6.6]),
["red", "green", "blue"], ["red", "green", "blue"],
], ],
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([2, 4, 6]), new Dataframe.DenseInt32Index([2, 4, 6]),
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"]) new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
); );
const dfA = sourceDf.isubsetMask( const dfA = sourceDf.isubsetMask(
new Uint8Array([0, 1, 1]), new Uint8Array([0, 1, 1]),
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'Uint8Array' is not assignable to... Remove this comment to see the full error message
new Uint8Array([1, 0, 0, 1]) new Uint8Array([1, 0, 0, 1])
); );
expect(dfA.dims).toEqual([2, 2]); expect(dfA.dims).toEqual([2, 2]);
@@ -303,6 +316,7 @@ describe("dataframe subsetting", () => {
["red", "green", "blue"], ["red", "green", "blue"],
], ],
null, // identity index null, // identity index
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"]) new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
); );
@@ -316,6 +330,7 @@ describe("dataframe subsetting", () => {
}); });
test("all rows, two cols", () => { test("all rows, two cols", () => {
// @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
const dfA = sourceDf.isubset(null, [1, 2]); const dfA = sourceDf.isubset(null, [1, 2]);
expect(dfA.dims).toEqual([3, 2]); expect(dfA.dims).toEqual([3, 2]);
expect(dfA.icol(0).asArray()).toEqual(["A", "B", "C"]); expect(dfA.icol(0).asArray()).toEqual(["A", "B", "C"]);
@@ -361,6 +376,7 @@ describe("dataframe factories", () => {
const dfA = new Dataframe.Dataframe( const dfA = new Dataframe.Dataframe(
[3, 2], [3, 2],
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])], [new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([2, 1, 0]), new Dataframe.DenseInt32Index([2, 1, 0]),
new Dataframe.KeyIndex(["A", "B"]) new Dataframe.KeyIndex(["A", "B"])
); );
@@ -385,6 +401,7 @@ describe("dataframe factories", () => {
[true, false], [true, false],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors", "bools"]) new Dataframe.KeyIndex(["colors", "bools"])
); );
const dfA = df.withCol("numbers", [1, 0]); const dfA = df.withCol("numbers", [1, 0]);
@@ -408,6 +425,7 @@ describe("dataframe factories", () => {
[true, false], [true, false],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([74, 75]) new Dataframe.DenseInt32Index([74, 75])
); );
const dfA = df.withCol(72, [1, 0]); const dfA = df.withCol(72, [1, 0]);
@@ -433,6 +451,7 @@ describe("dataframe factories", () => {
[true, false], [true, false],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([74, 75]) new Dataframe.DenseInt32Index([74, 75])
); );
const dfA = df.withCol(999, [1, 0]); const dfA = df.withCol(999, [1, 0]);
@@ -541,6 +560,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors", "bools", "numbers"]) new Dataframe.KeyIndex(["colors", "bools", "numbers"])
); );
@@ -549,11 +569,14 @@ describe("dataframe factories", () => {
[3, 1], [3, 1],
[["red", "blue", "green"]], [["red", "blue", "green"]],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colorsA"]) new Dataframe.KeyIndex(["colorsA"])
); );
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
expect(() => dfA.withColsFrom(dfB)).toThrow(RangeError); expect(() => dfA.withColsFrom(dfB)).toThrow(RangeError);
/* duplicate labels should throw an error */ /* duplicate labels should throw an error */
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
expect(() => dfA.withColsFrom(dfA)).toThrow(Error); expect(() => dfA.withColsFrom(dfA)).toThrow(Error);
}); });
@@ -564,15 +587,18 @@ describe("dataframe factories", () => {
[2, 1], [2, 1],
[["red", "blue"]], [["red", "blue"]],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors"]) new Dataframe.KeyIndex(["colors"])
); );
const dfB = new Dataframe.Dataframe( const dfB = new Dataframe.Dataframe(
[2, 1], [2, 1],
[[true, false]], [[true, false]],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["bools"]) new Dataframe.KeyIndex(["bools"])
); );
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const dfLikeA = dfEmpty.withColsFrom(dfA); const dfLikeA = dfEmpty.withColsFrom(dfA);
expect(dfLikeA).toBeDefined(); expect(dfLikeA).toBeDefined();
expect(dfLikeA.dims).toEqual(dfA.dims); expect(dfLikeA.dims).toEqual(dfA.dims);
@@ -581,6 +607,7 @@ describe("dataframe factories", () => {
expect(dfLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels()); expect(dfLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
expect(dfLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray()); expect(dfLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const dfAlsoLikeA = dfA.withColsFrom(dfEmpty); const dfAlsoLikeA = dfA.withColsFrom(dfEmpty);
expect(dfAlsoLikeA).toBeDefined(); expect(dfAlsoLikeA).toBeDefined();
expect(dfAlsoLikeA.dims).toEqual(dfA.dims); expect(dfAlsoLikeA.dims).toEqual(dfA.dims);
@@ -589,6 +616,7 @@ describe("dataframe factories", () => {
expect(dfAlsoLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels()); expect(dfAlsoLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
expect(dfAlsoLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray()); expect(dfAlsoLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const dfC = dfA.withColsFrom(dfB); const dfC = dfA.withColsFrom(dfB);
expect(dfC).toBeDefined(); expect(dfC).toBeDefined();
expect(dfC.dims).toEqual([2, 2]); expect(dfC.dims).toEqual([2, 2]);
@@ -605,6 +633,7 @@ describe("dataframe factories", () => {
[2, 1], [2, 1],
[["red", "blue"]], [["red", "blue"]],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors"]) new Dataframe.KeyIndex(["colors"])
); );
const dfB = new Dataframe.Dataframe( const dfB = new Dataframe.Dataframe(
@@ -615,6 +644,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors", "bools", "numbers"]) new Dataframe.KeyIndex(["colors", "bools", "numbers"])
); );
@@ -647,6 +677,7 @@ describe("dataframe factories", () => {
[2, 1], [2, 1],
[["red", "blue"]], [["red", "blue"]],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors"]) new Dataframe.KeyIndex(["colors"])
); );
const dfB = new Dataframe.Dataframe( const dfB = new Dataframe.Dataframe(
@@ -657,6 +688,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors", "bools", "numbers"]) new Dataframe.KeyIndex(["colors", "bools", "numbers"])
); );
@@ -680,6 +712,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["colors", "bools", "numbers"]) new Dataframe.KeyIndex(["colors", "bools", "numbers"])
); );
const dfA = df.dropCol("colors"); const dfA = df.dropCol("colors");
@@ -751,6 +784,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
new Dataframe.DenseInt32Index([102, 101, 100]) new Dataframe.DenseInt32Index([102, 101, 100])
); );
const dfA = df.dropCol(101); const dfA = df.dropCol(101);
@@ -777,7 +811,7 @@ describe("dataframe factories", () => {
new Float64Array(3).fill(1.1), new Float64Array(3).fill(1.1),
] ]
); );
const dfB = dfA.mapColumns((col, idx) => { const dfB = dfA.mapColumns((col: any, idx: any) => {
expect(dfA.icol(idx).asArray()).toBe(col); expect(dfA.icol(idx).asArray()).toBe(col);
return col; return col;
}); });
@@ -822,6 +856,7 @@ describe("dataframe factories", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["A", "B"]) new Dataframe.KeyIndex(["A", "B"])
); );
const dfB = dfA.renameCol("B", "C"); const dfB = dfA.renameCol("B", "C");
@@ -834,7 +869,7 @@ describe("dataframe factories", () => {
}); });
describe("dataframe col", () => { describe("dataframe col", () => {
let df = null; let df: any = null;
beforeEach(() => { beforeEach(() => {
df = new Dataframe.Dataframe( df = new Dataframe.Dataframe(
[2, 2], [2, 2],
@@ -843,6 +878,7 @@ describe("dataframe col", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["A", "B"]) new Dataframe.KeyIndex(["A", "B"])
); );
}); });
@@ -1195,6 +1231,7 @@ describe("label indexing", () => {
test("create", () => { test("create", () => {
expect(Dataframe.isLabelIndex(idx)).toBeTruthy(); expect(Dataframe.isLabelIndex(idx)).toBeTruthy();
expect(() => new Dataframe.KeyIndex(["dup", "dup"])).toThrow(Error); expect(() => new Dataframe.KeyIndex(["dup", "dup"])).toThrow(Error);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
expect(new Dataframe.KeyIndex().size()).toEqual(0); expect(new Dataframe.KeyIndex().size()).toEqual(0);
}); });
@@ -1367,6 +1404,7 @@ describe("corner cases", () => {
[1, 0], [1, 0],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["A", "B"]) new Dataframe.KeyIndex(["A", "B"])
); );
@@ -6,6 +6,7 @@ describe("Dataframe column histogram", () => {
[3, 3], [3, 3],
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])], [["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["name", "cat", "value"]) new Dataframe.KeyIndex(["name", "cat", "value"])
); );
@@ -26,6 +27,7 @@ describe("Dataframe column histogram", () => {
[3, 3], [3, 3],
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])], [["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["name", "cat", "value"]) new Dataframe.KeyIndex(["name", "cat", "value"])
); );
@@ -48,6 +50,7 @@ describe("Dataframe column histogram", () => {
[3, 3], [3, 3],
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])], [["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["name", "cat", "value"]) new Dataframe.KeyIndex(["name", "cat", "value"])
); );
@@ -68,6 +71,7 @@ describe("Dataframe column histogram", () => {
[3, 3], [3, 3],
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])], [["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["name", "cat", "value"]) new Dataframe.KeyIndex(["name", "cat", "value"])
); );
@@ -1,6 +1,6 @@
import * as Dataframe from "../../../src/util/dataframe"; import * as Dataframe from "../../../src/util/dataframe";
function float32Conversion(f) { function float32Conversion(f: any) {
return new Float32Array([f])[0]; return new Float32Array([f])[0];
} }
@@ -30,6 +30,7 @@ describe("Dataframe column summary", () => {
[1], [1],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex([ new Dataframe.KeyIndex([
"name", "name",
"nameString", "nameString",
@@ -106,6 +107,7 @@ describe("Dataframe column summary", () => {
[1, false, "0"], [1, false, "0"],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex([ new Dataframe.KeyIndex([
"name", "name",
"nameString", "nameString",
@@ -174,6 +176,7 @@ describe("Dataframe column summary", () => {
expect.objectContaining({ expect.objectContaining({
categorical: true, categorical: true,
categories: expect.arrayContaining([1, false, "0"]), categories: expect.arrayContaining([1, false, "0"]),
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
categoryCounts: new Map([ categoryCounts: new Map([
[1, 1], [1, 1],
[false, 1], [false, 1],
@@ -201,6 +204,7 @@ describe("Dataframe column summary", () => {
[1, false, "0", "0"], [1, false, "0", "0"],
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex([ new Dataframe.KeyIndex([
"name", "name",
"nameString", "nameString",
@@ -269,6 +273,7 @@ describe("Dataframe column summary", () => {
expect.objectContaining({ expect.objectContaining({
categorical: true, categorical: true,
categories: expect.arrayContaining([1, false, "0"]), categories: expect.arrayContaining([1, false, "0"]),
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
categoryCounts: new Map([ categoryCounts: new Map([
[1, 1], [1, 1],
[false, 1], [false, 1],
@@ -1,7 +1,7 @@
import PromiseLimit from "../../src/util/promiseLimit"; import PromiseLimit from "../../src/util/promiseLimit";
import { range } from "../../src/util/range"; import { range } from "../../src/util/range";
const delay = (t) => new Promise((resolve) => setTimeout(resolve, t)); const delay = (t: any) => new Promise((resolve) => setTimeout(resolve, t));
describe("PromiseLimit", () => { describe("PromiseLimit", () => {
test("simple evaluation, concurrency 1", async () => { test("simple evaluation, concurrency 1", async () => {
@@ -51,7 +51,8 @@ describe("PromiseLimit", () => {
running -= 1; running -= 1;
}; };
await Promise.all(range(10).map((i) => plimit.add(() => callback(i)))); // @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
await Promise.all(range(10).map((i: any) => plimit.add(() => callback(i))));
expect(maxRunning).toEqual(2); expect(maxRunning).toEqual(2);
}); });
@@ -6,14 +6,20 @@ describe("range", () => {
}); });
test("range(stop)", () => { test("range(stop)", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
expect(range(3)).toMatchObject([0, 1, 2]); expect(range(3)).toMatchObject([0, 1, 2]);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
expect(range(0)).toMatchObject([]); expect(range(0)).toMatchObject([]);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
expect(range(1)).toMatchObject([0]); expect(range(1)).toMatchObject([0]);
}); });
test("range(start,stop)", () => { test("range(start,stop)", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
expect(range(0, 0)).toMatchObject([]); expect(range(0, 0)).toMatchObject([]);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
expect(range(0, 2)).toMatchObject([0, 1]); expect(range(0, 2)).toMatchObject([0, 1]);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
expect(range(4, 8)).toMatchObject([4, 5, 6, 7]); expect(range(4, 8)).toMatchObject([4, 5, 6, 7]);
}); });
@@ -81,6 +81,7 @@ describe("categorical color helpers", () => {
), ),
], ],
null, null,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
new Dataframe.KeyIndex(["continuousColumn", "categoricalColumn"]) new Dataframe.KeyIndex(["continuousColumn", "categoricalColumn"])
); );
@@ -95,6 +96,7 @@ describe("categorical color helpers", () => {
const data = obsDataframe.col("categoricalColumn").asArray(); const data = obsDataframe.col("categoricalColumn").asArray();
const cats = schema.annotations.obsByName.categoricalColumn.categories; const cats = schema.annotations.obsByName.categoricalColumn.categories;
for (let i = 0; i < schema.dataframe.nObs; i += 1) { for (let i = 0; i < schema.dataframe.nObs; i += 1) {
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i]))); expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i])));
} }
}); });
@@ -112,6 +114,7 @@ describe("categorical color helpers", () => {
const data = obsDataframe.col("categoricalColumn").asArray(); const data = obsDataframe.col("categoricalColumn").asArray();
const cats = schemaClone.annotations.obsByName.categoricalColumn.categories; const cats = schemaClone.annotations.obsByName.categoricalColumn.categories;
for (let i = 0; i < schemaClone.dataframe.nObs; i += 1) { for (let i = 0; i < schemaClone.dataframe.nObs; i += 1) {
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i]))); expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i])));
} }
}); });
@@ -122,7 +125,7 @@ describe("categorical color helpers", () => {
Array.from(schema.annotations.obsByName.categoricalColumn.categories) Array.from(schema.annotations.obsByName.categoricalColumn.categories)
); );
const userDefinedColorTable = { const userDefinedColorTable = {
categoricalColumn: shuffleCats.reduce((acc, label) => { categoricalColumn: shuffleCats.reduce((acc: any, label: any) => {
acc[label] = randRGBColor(); acc[label] = randRGBColor();
return acc; return acc;
}, {}), }, {}),
@@ -136,12 +139,14 @@ describe("categorical color helpers", () => {
"categoricalColumn", "categoricalColumn",
obsDataframe, obsDataframe,
schema, schema,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{}' is not assignable to paramet... Remove this comment to see the full error message
userColors userColors
); );
expect(ct).toBeDefined(); expect(ct).toBeDefined();
const data = obsDataframe.col("categoricalColumn").asArray(); const data = obsDataframe.col("categoricalColumn").asArray();
for (let i = 0; i < schema.dataframe.nObs; i += 1) { for (let i = 0; i < schema.dataframe.nObs; i += 1) {
expect(makeScale(ct.rgb[i])).toEqual( expect(makeScale(ct.rgb[i])).toEqual(
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
ct.scale(cats.indexOf(data[i])).toString() ct.scale(cats.indexOf(data[i])).toString()
); );
} }
@@ -154,31 +159,31 @@ TODO:
2. user defined colors 2. user defined colors
*/ */
function indexSchema(schema) { function indexSchema(schema: any) {
schema.annotations.obsByName = Object.fromEntries( schema.annotations.obsByName = Object.fromEntries(
schema.annotations?.obs?.columns?.map((v) => [v.name, v]) ?? [] schema.annotations?.obs?.columns?.map((v: any) => [v.name, v]) ?? []
); );
schema.annotations.varByName = Object.fromEntries( schema.annotations.varByName = Object.fromEntries(
schema.annotations?.var?.columns?.map((v) => [v.name, v]) ?? [] schema.annotations?.var?.columns?.map((v: any) => [v.name, v]) ?? []
); );
schema.layout.obsByName = Object.fromEntries( schema.layout.obsByName = Object.fromEntries(
schema.layout?.obs?.map((v) => [v.name, v]) ?? [] schema.layout?.obs?.map((v: any) => [v.name, v]) ?? []
); );
schema.layout.varByName = Object.fromEntries( schema.layout.varByName = Object.fromEntries(
schema.layout?.var?.map((v) => [v.name, v]) ?? [] schema.layout?.var?.map((v: any) => [v.name, v]) ?? []
); );
return schema; return schema;
} }
function makeScale(rgb) { function makeScale(rgb: any) {
// make a scale string from a rgb float triple // make a scale string from a rgb float triple
return `rgb(${(rgb[0] * 255) >>> 0}, ${(rgb[1] * 255) >>> 0}, ${ return `rgb(${(rgb[0] * 255) >>> 0}, ${(rgb[1] * 255) >>> 0}, ${
(rgb[2] * 256) >>> 0 (rgb[2] * 256) >>> 0
})`; })`;
} }
function shuffle(array) { function shuffle(array: any) {
for (let i = array.length - 1; i > 0; i -= 1) { for (let i = array.length - 1; i > 0; i -= 1) {
const j = (Math.random() * (i + 1)) >>> 0; const j = (Math.random() * (i + 1)) >>> 0;
[array[i], array[j]] = [array[j], array[i]]; [array[i], array[j]] = [array[j], array[i]];
@@ -24,6 +24,7 @@ describe("encode/decode", () => {
expect(dfA.columns).toEqual(columns); expect(dfA.columns).toEqual(columns);
const colIndex = new KeyIndex(["a", "b", "c", "d"]); const colIndex = new KeyIndex(["a", "b", "c", "d"]);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
const dfWithColIdx = new Dataframe([3, 4], columns, null, colIndex); const dfWithColIdx = new Dataframe([3, 4], columns, null, colIndex);
const dfB = decodeMatrixFBS(encodeMatrixFBS(dfWithColIdx)); const dfB = decodeMatrixFBS(encodeMatrixFBS(dfWithColIdx));
expect([dfB.nRows, dfB.nCols]).toEqual(dfWithColIdx.dims); expect([dfB.nRows, dfB.nCols]).toEqual(dfWithColIdx.dims);
@@ -75,6 +75,7 @@ const aSchemaResponse = {
const anAnnotationsObsJSONResponse = { const anAnnotationsObsJSONResponse = {
names: ["name", "field1", "field2", "field3", "field4"], names: ["name", "field1", "field2", "field3", "field4"],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
data: _() data: _()
.range(nObs) .range(nObs)
.map((idx) => [ .map((idx) => [
@@ -91,6 +92,7 @@ const anAnnotationsObsJSONResponse = {
const anAnnotationsVarJSONResponse = { const anAnnotationsVarJSONResponse = {
names: ["fieldA", "fieldB", "fieldC", "fieldD", "name"], names: ["fieldA", "fieldB", "fieldC", "fieldD", "name"],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
data: _() data: _()
.range(nVar) .range(nVar)
.map((idx) => [ .map((idx) => [
@@ -105,7 +107,7 @@ const anAnnotationsVarJSONResponse = {
.value(), .value(),
}; };
function encodeTypedArray(builder, uType, uData) { function encodeTypedArray(builder: any, uType: any, uData: any) {
const uTypeName = NetEncoding.TypedArray[uType]; const uTypeName = NetEncoding.TypedArray[uType];
const ArrayType = NetEncoding[uTypeName]; const ArrayType = NetEncoding[uTypeName];
const dv = ArrayType.createDataVector(builder, uData); const dv = ArrayType.createDataVector(builder, uData);
@@ -114,7 +116,7 @@ function encodeTypedArray(builder, uType, uData) {
return builder.endObject(); return builder.endObject();
} }
function encodeMatrix(columns, colIndex = undefined) { function encodeMatrix(columns: any, colIndex = undefined) {
/* /*
IMPORTANT: this is not a general purpose encoder. in particular, IMPORTANT: this is not a general purpose encoder. in particular,
it doesn't correctly handle all column index types, nor does it it doesn't correctly handle all column index types, nor does it
@@ -123,6 +125,7 @@ function encodeMatrix(columns, colIndex = undefined) {
encodeMatrixFBS in matrix.py is more general. This is used only encodeMatrixFBS in matrix.py is more general. This is used only
as a testing santity check (alt implementation). as a testing santity check (alt implementation).
*/ */
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
const utf8Encoder = new TextEncoder("utf-8"); const utf8Encoder = new TextEncoder("utf-8");
const builder = new flatbuffers.Builder(1024); const builder = new flatbuffers.Builder(1024);
const cols = map(columns, (carr) => { const cols = map(columns, (carr) => {
@@ -172,11 +175,13 @@ function encodeMatrix(columns, colIndex = undefined) {
const anAnnotationsObsFBSResponse = (() => { const anAnnotationsObsFBSResponse = (() => {
const columns = zip(...anAnnotationsObsJSONResponse.data).slice(1); const columns = zip(...anAnnotationsObsJSONResponse.data).slice(1);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(columns, anAnnotationsObsJSONResponse.names); return encodeMatrix(columns, anAnnotationsObsJSONResponse.names);
})(); })();
const anAnnotationsVarFBSResponse = (() => { const anAnnotationsVarFBSResponse = (() => {
const columns = zip(...anAnnotationsVarJSONResponse.data).slice(1); const columns = zip(...anAnnotationsVarJSONResponse.data).slice(1);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(columns, anAnnotationsVarJSONResponse.names); return encodeMatrix(columns, anAnnotationsVarJSONResponse.names);
})(); })();
@@ -185,11 +190,13 @@ const aLayoutFBSResponse = (() => {
new Float32Array(nObs).fill(Math.random()), new Float32Array(nObs).fill(Math.random()),
new Float32Array(nObs).fill(Math.random()), new Float32Array(nObs).fill(Math.random()),
]; ];
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(coords, ["umap_0", "umap_1"]); return encodeMatrix(coords, ["umap_0", "umap_1"]);
})(); })();
const aDataObsResponse = { const aDataObsResponse = {
var: [2, 4, 29], var: [2, 4, 29],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
obs: _() obs: _()
.range(nObs) .range(nObs)
.map((idx) => [idx, Math.random(), Math.random(), Math.random()]) .map((idx) => [idx, Math.random(), Math.random(), Math.random()])
@@ -126,7 +126,7 @@ const someData = [
}, },
]; ];
let payments = null; let payments: any = null;
beforeEach(() => { beforeEach(() => {
payments = new Crossfilter(someData); payments = new Crossfilter(someData);
}); });
@@ -138,7 +138,12 @@ describe("ImmutableTypedCrossfilter", () => {
expect(payments.all()).toEqual(someData); expect(payments.all()).toEqual(someData);
const p = payments const p = payments
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .addDimension(
"quantity",
"scalar",
(i: any, d: any) => d[i].quantity,
Int32Array
)
.select("quantity", { mode: "all" }); .select("quantity", { mode: "all" });
expect(p).toBeDefined(); expect(p).toBeDefined();
expect(p.all()).toEqual(someData); expect(p.all()).toEqual(someData);
@@ -158,7 +163,7 @@ describe("ImmutableTypedCrossfilter", () => {
const p2 = payments.addDimension( const p2 = payments.addDimension(
"quantity", "quantity",
"scalar", "scalar",
(i, data) => data[i].quantity, (i: any, data: any) => data[i].quantity,
Int32Array Int32Array
); );
@@ -175,10 +180,20 @@ describe("ImmutableTypedCrossfilter", () => {
test("select all and none", () => { test("select all and none", () => {
let p = payments let p = payments
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .addDimension(
.addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array) "quantity",
.addDimension("total", "scalar", (i, d) => d[i].total, Float32Array) "scalar",
.addDimension("type", "enum", (i, d) => d[i].type); (i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension("tip", "scalar", (i: any, d: any) => d[i].tip, Float32Array)
.addDimension(
"total",
"scalar",
(i: any, d: any) => d[i].total,
Float32Array
)
.addDimension("type", "enum", (i: any, d: any) => d[i].type);
expect(p).toBeDefined(); expect(p).toBeDefined();
/* expect all records to be selected - default init state */ /* expect all records to be selected - default init state */
@@ -230,11 +245,21 @@ describe("ImmutableTypedCrossfilter", () => {
}); });
describe("scalar dimension", () => { describe("scalar dimension", () => {
let p; let p: any;
beforeEach(() => { beforeEach(() => {
p = payments p = payments
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .addDimension(
.addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array) "quantity",
"scalar",
(i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension(
"tip",
"scalar",
(i: any, d: any) => d[i].tip,
Float32Array
)
.select("tip", { mode: "all" }); .select("tip", { mode: "all" });
}); });
@@ -277,9 +302,9 @@ describe("ImmutableTypedCrossfilter", () => {
}); });
describe("enum dimension", () => { describe("enum dimension", () => {
let p; let p: any;
beforeEach(() => { beforeEach(() => {
p = payments.addDimension("type", "enum", (i, d) => d[i].type); p = payments.addDimension("type", "enum", (i: any, d: any) => d[i].type);
}); });
test("all", () => { test("all", () => {
@@ -317,7 +342,7 @@ describe("ImmutableTypedCrossfilter", () => {
}); });
describe("spatial dimension", () => { describe("spatial dimension", () => {
let p; let p: any;
beforeEach(() => { beforeEach(() => {
const X = someData.map((r) => r.coords[0]); const X = someData.map((r) => r.coords[0]);
const Y = someData.map((r) => r.coords[1]); const Y = someData.map((r) => r.coords[1]);
@@ -406,14 +431,19 @@ describe("ImmutableTypedCrossfilter", () => {
}); });
describe("non-finite scalars", () => { describe("non-finite scalars", () => {
let p; let p: any;
beforeEach(() => { beforeEach(() => {
p = payments p = payments
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .addDimension(
"quantity",
"scalar",
(i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension( .addDimension(
"nonFinite", "nonFinite",
"scalar", "scalar",
(i, d) => d[i].nonFinite, (i: any, d: any) => d[i].nonFinite,
Float32Array Float32Array
) )
.select("quantity", { mode: "all" }); .select("quantity", { mode: "all" });
@@ -15,7 +15,7 @@ paths for:
const pInf = Number.POSITIVE_INFINITY; const pInf = Number.POSITIVE_INFINITY;
const nInf = Number.NEGATIVE_INFINITY; const nInf = Number.NEGATIVE_INFINITY;
function fillRange(arr, start = 0) { function fillRange(arr: any, start = 0) {
const larr = arr; const larr = arr;
for (let i = 0, len = larr.length; i < len; i += 1) { for (let i = 0, len = larr.length; i < len; i += 1) {
larr[i] = i + start; larr[i] = i + start;
@@ -23,7 +23,7 @@ function fillRange(arr, start = 0) {
return larr; return larr;
} }
function fillRand(arr) { function fillRand(arr: any) {
for (let i = 0, len = arr.length; i < len; i += 1) { for (let i = 0, len = arr.length; i < len; i += 1) {
arr[i] = Math.random(); arr[i] = Math.random();
} }
@@ -48,16 +48,22 @@ describe("sortArray", () => {
describe("finite numbers", () => { describe("finite numbers", () => {
[Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) => [Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) =>
test(Type.name, () => { test(Type.name, () => {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from([6, 5, 4, 3, 2, 1, 0]))).toMatchObject( expect(sortArray(Type.from([6, 5, 4, 3, 2, 1, 0]))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from([0, 1, 2, 3, 4, 5, 6]) Type.from([0, 1, 2, 3, 4, 5, 6])
); );
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from([6, 5, 4, 3, 2, 1]))).toMatchObject( expect(sortArray(Type.from([6, 5, 4, 3, 2, 1]))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from([1, 2, 3, 4, 5, 6]) Type.from([1, 2, 3, 4, 5, 6])
); );
const source = fillRand(new Type(1000)); const source = fillRand(new Type(1000));
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from(source))).toMatchObject( expect(sortArray(Type.from(source))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from(source).sort() Type.from(source).sort()
); );
}) })
@@ -130,22 +136,24 @@ describe("sortIndex", () => {
describe("finite numbers", () => { describe("finite numbers", () => {
[Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) => [Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) =>
test(Type.name, () => { test(Type.name, () => {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
const source1 = Type.from([6, 5, 4, 3, 2, 1, 0]); const source1 = Type.from([6, 5, 4, 3, 2, 1, 0]);
const index1 = fillRange(new Uint32Array(source1.length)); const index1 = fillRange(new Uint32Array(source1.length));
expect(sortIndex(index1, source1)).toMatchObject( expect(sortIndex(index1, source1)).toMatchObject(
index1.sort((a, b) => source1[a] - source1[b]) index1.sort((a: any, b: any) => source1[a] - source1[b])
); );
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
const source2 = Type.from([6, 5, 4, 3, 2, 1]); const source2 = Type.from([6, 5, 4, 3, 2, 1]);
const index2 = fillRange(new Uint32Array(source2.length)); const index2 = fillRange(new Uint32Array(source2.length));
expect(sortIndex(index2, source2)).toMatchObject( expect(sortIndex(index2, source2)).toMatchObject(
index2.sort((a, b) => source1[a] - source1[b]) index2.sort((a: any, b: any) => source1[a] - source1[b])
); );
const source3 = fillRand(new Type(1000)); const source3 = fillRand(new Type(1000));
const index3 = fillRange(new Uint32Array(source3.length)); const index3 = fillRange(new Uint32Array(source3.length));
expect(sortIndex(index3, source3)).toMatchObject( expect(sortIndex(index3, source3)).toMatchObject(
index3.sort((a, b) => source1[a] - source1[b]) index3.sort((a: any, b: any) => source1[a] - source1[b])
); );
}) })
); );
+1
View File
@@ -11,6 +11,7 @@ module.exports = {
}, },
], ],
"@babel/preset-react", "@babel/preset-react",
"@babel/preset-typescript",
], ],
plugins: [ plugins: [
"@babel/plugin-proposal-function-bind", "@babel/plugin-proposal-function-bind",
+1
View File
@@ -10,6 +10,7 @@ module.exports = {
}, },
], ],
"@babel/preset-react", "@babel/preset-react",
"@babel/preset-typescript"
], ],
plugins: [ plugins: [
"@babel/plugin-proposal-function-bind", "@babel/plugin-proposal-function-bind",
+34 -5
View File
@@ -1,13 +1,12 @@
module.exports = { module.exports = {
root: true, root: true,
parser: "babel-eslint", parser: "@typescript-eslint/parser",
extends: [ extends: [
"airbnb", "airbnb-typescript",
"plugin:eslint-comments/recommended", "plugin:eslint-comments/recommended",
"plugin:@blueprintjs/recommended", "plugin:@blueprintjs/recommended",
"plugin:compat/recommended", "plugin:compat/recommended",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"prettier",
], ],
settings: { settings: {
// AbortController is not supported in iOS Safari 10.3, Chrome 61 // AbortController is not supported in iOS Safari 10.3, Chrome 61
@@ -32,18 +31,47 @@ module.exports = {
jsx: true, jsx: true,
generators: true, generators: true,
}, },
project: "./tsconfig.json",
}, },
rules: { rules: {
"react/jsx-no-target-blank": "off", "react/jsx-no-target-blank": "off",
"eslint-comments/require-description": ["error"], "eslint-comments/require-description": ["error"],
"no-magic-numbers": "off", "no-magic-numbers": "off",
"@typescript-eslint/no-magic-numbers": "off",
"no-nested-ternary": "off", "no-nested-ternary": "off",
"func-style": "off", "func-style": "off",
"arrow-parens": "off", "arrow-parens": "off",
"no-use-before-define": "off", "no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "off",
"react/jsx-filename-extension": "off", "react/jsx-filename-extension": "off",
"comma-dangle": "off", "comma-dangle": "off",
"@typescript-eslint/comma-dangle": "off",
"no-underscore-dangle": "off", "no-underscore-dangle": "off",
// Override airbnb config to allow leading underscore
// https://github.com/iamturns/eslint-config-airbnb-typescript/blob/master/lib/shared.js#L35
"@typescript-eslint/naming-convention": [
"error",
{
selector: "class",
format: ["PascalCase"],
leadingUnderscore: "allow",
},
{
selector: "function",
format: ["camelCase", "PascalCase"],
leadingUnderscore: "allowSingleOrDouble",
},
{
selector: "typeLike",
format: ["PascalCase"],
},
{
selector: "variable",
format: ["camelCase", "PascalCase", "UPPER_CASE"],
leadingUnderscore: "allowSingleOrDouble",
trailingUnderscore: "allowDouble",
},
],
"implicit-arrow-linebreak": "off", "implicit-arrow-linebreak": "off",
"no-console": "off", "no-console": "off",
"spaced-comment": ["error", "always", { exceptions: ["*"] }], "spaced-comment": ["error", "always", { exceptions: ["*"] }],
@@ -51,6 +79,7 @@ module.exports = {
"object-curly-newline": ["error", { consistent: true }], "object-curly-newline": ["error", { consistent: true }],
"react/prop-types": [0], "react/prop-types": [0],
"space-before-function-paren": "off", "space-before-function-paren": "off",
"@typescript-eslint/space-before-function-paren": "off",
"function-paren-newline": "off", "function-paren-newline": "off",
"prefer-destructuring": ["error", { object: true, array: false }], "prefer-destructuring": ["error", { object: true, array: false }],
"import/prefer-default-export": "off", "import/prefer-default-export": "off",
@@ -69,9 +98,9 @@ module.exports = {
}, },
overrides: [ overrides: [
{ {
files: ["**/*.test.js"], files: ["**/*.test.ts"],
env: { env: {
jest: true, // now **/*.test.js files' env has both es6 *and* jest jest: true, // now **/*.test.ts files' env has both es6 *and* jest
}, },
// Can't extend in overrides: https://github.com/eslint/eslint/issues/8813 // Can't extend in overrides: https://github.com/eslint/eslint/issues/8813
// "extends": ["plugin:jest/recommended"] // "extends": ["plugin:jest/recommended"]
@@ -1,3 +1,3 @@
module.exports = { module.exports = {
"*.js": "eslint --fix", "*.{js,ts,jsx,tsx}": "eslint --fix",
}; };
@@ -23,7 +23,7 @@ const devConfig = {
module: { module: {
rules: [ rules: [
{ {
test: /\.jsx?$/, test: /\.(ts|js)x?$/,
loader: "babel-loader", loader: "babel-loader",
options: babelOptions, options: babelOptions,
}, },
@@ -38,7 +38,7 @@ const prodConfig = {
module: { module: {
rules: [ rules: [
{ {
test: /\.jsx?$/, test: /\.(ts|js)x?$/,
loader: "babel-loader", loader: "babel-loader",
options: babelOptions, options: babelOptions,
}, },
@@ -29,6 +29,9 @@ module.exports = {
path: path.resolve("build"), path: path.resolve("build"),
publicPath, publicPath,
}, },
resolve: {
extensions: [".ts", ".tsx", "..."],
},
module: { module: {
rules: [ rules: [
{ {
+1612 -388
View File
File diff suppressed because it is too large Load Diff
+37 -7
View File
@@ -8,9 +8,9 @@
"build": "npm run clean && webpack --config", "build": "npm run clean && webpack --config",
"clean": "rimraf build", "clean": "rimraf build",
"dev": "npm run build -- configuration/webpack/webpack.config.dev.js", "dev": "npm run build -- configuration/webpack/webpack.config.dev.js",
"e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.js", "e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.ts",
"e2e-annotations": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2eAnnotations.test.js", "e2e-annotations": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2eAnnotations.test.ts",
"e2e-prod": "CXG_URL_BASE='https://cellxgene.cziscience.com/d/pbmc3k.cxg/' jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.js", "e2e-prod": "CXG_URL_BASE='https://cellxgene.cziscience.com/d/pbmc3k.cxg/' jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.ts",
"fmt": "eslint --fix src __tests__", "fmt": "eslint --fix src __tests__",
"lint": "eslint --fix src __tests__", "lint": "eslint --fix src __tests__",
"prod": "npm run build -- configuration/webpack/webpack.config.prod.js", "prod": "npm run build -- configuration/webpack/webpack.config.prod.js",
@@ -90,10 +90,38 @@
"@babel/plugin-transform-runtime": "^7.13.15", "@babel/plugin-transform-runtime": "^7.13.15",
"@babel/preset-env": "^7.13.15", "@babel/preset-env": "^7.13.15",
"@babel/preset-react": "^7.13.13", "@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.14.5",
"@babel/register": "^7.13.16", "@babel/register": "^7.13.16",
"@babel/runtime": "^7.13.16", "@babel/runtime": "^7.13.16",
"@blueprintjs/eslint-plugin": "^0.3.0", "@blueprintjs/eslint-plugin": "^0.3.0",
"@sentry/webpack-plugin": "^1.15.0", "@sentry/webpack-plugin": "^1.15.0",
"@types/d3": "^7.0.0",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/expect-puppeteer": "^4.4.6",
"@types/flatbuffers": "^1.10.0",
"@types/is-number": "^7.0.1",
"@types/jest": "^26.0.24",
"@types/jest-environment-puppeteer": "^4.4.1",
"@types/lodash.clonedeep": "^4.5.6",
"@types/lodash.difference": "^4.5.6",
"@types/lodash.every": "^4.6.6",
"@types/lodash.filter": "^4.6.6",
"@types/lodash.foreach": "^4.5.6",
"@types/lodash.isnumber": "^3.0.6",
"@types/lodash.map": "^4.6.13",
"@types/lodash.pull": "^4.1.6",
"@types/lodash.sortby": "^4.7.6",
"@types/lodash.uniq": "^4.5.6",
"@types/lodash.zip": "^4.2.6",
"@types/pako": "^1.0.2",
"@types/puppeteer": "^5.4.4",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"@types/react-helmet": "^6.1.2",
"@types/react-redux": "^7.1.18",
"@types/sha1": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^4.28.4",
"@typescript-eslint/parser": "^4.28.4",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-jest": "^26.1.0", "babel-jest": "^26.1.0",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
@@ -106,7 +134,7 @@
"connect-history-api-fallback": "^1.6.0", "connect-history-api-fallback": "^1.6.0",
"css-loader": "^5.2.4", "css-loader": "^5.2.4",
"eslint": "^7.24.0", "eslint": "^7.24.0",
"eslint-config-airbnb": "^18.2.0", "eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-prettier": "^8.2.0", "eslint-config-prettier": "^8.2.0",
"eslint-loader": "^4.0.2", "eslint-loader": "^4.0.2",
"eslint-plugin-compat": "^3.8.0", "eslint-plugin-compat": "^3.8.0",
@@ -149,6 +177,7 @@
"style-loader": "^2.0.0", "style-loader": "^2.0.0",
"sw-precache-webpack-plugin": "^1.0.0", "sw-precache-webpack-plugin": "^1.0.0",
"terser-webpack-plugin": "^5.1.1", "terser-webpack-plugin": "^5.1.1",
"typescript": "^4.3.5",
"url-loader": "^4.1.0", "url-loader": "^4.1.0",
"webpack": "^5.34.0", "webpack": "^5.34.0",
"webpack-cli": "^4.6.0", "webpack-cli": "^4.6.0",
@@ -157,10 +186,10 @@
}, },
"jest": { "jest": {
"testMatch": [ "testMatch": [
"**/__tests__/**/?(*.)(spec|test).js?(x)" "**/__tests__/**/?(*.)(spec|test).ts?(x)"
], ],
"setupFiles": [ "setupFiles": [
"./__tests__/setupMissingGlobals.js" "./__tests__/setupMissingGlobals.ts"
], ],
"coverageDirectory": "./coverage/", "coverageDirectory": "./coverage/",
"collectCoverage": true "collectCoverage": true
@@ -170,7 +199,8 @@
"test": { "test": {
"presets": [ "presets": [
"@babel/preset-env", "@babel/preset-env",
"@babel/preset-react" "@babel/preset-react",
"@babel/preset-typescript"
], ],
"plugins": [ "plugins": [
"@babel/plugin-proposal-function-bind", "@babel/plugin-proposal-function-bind",
@@ -9,9 +9,9 @@ import { MatrixFBS, AnnotationsHelpers } from "../util/stateManager";
const { isUserAnnotation } = AnnotationsHelpers; const { isUserAnnotation } = AnnotationsHelpers;
export const annotationCreateCategoryAction = ( export const annotationCreateCategoryAction = (
newCategoryName, newCategoryName: any,
categoryToDuplicate categoryToDuplicate: any
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
/* /*
Add a new user-created category to the obs annotations. Add a new user-created category to the obs annotations.
@@ -89,9 +89,9 @@ export const annotationCreateCategoryAction = (
}; };
export const annotationRenameCategoryAction = ( export const annotationRenameCategoryAction = (
oldCategoryName, oldCategoryName: any,
newCategoryName newCategoryName: any
) => (dispatch, getState) => { ) => (dispatch: any, getState: any) => {
/* /*
Rename a user-created annotation category Rename a user-created annotation category
*/ */
@@ -124,9 +124,9 @@ export const annotationRenameCategoryAction = (
}); });
}; };
export const annotationDeleteCategoryAction = (categoryName) => ( export const annotationDeleteCategoryAction = (categoryName: any) => (
dispatch, dispatch: any,
getState getState: any
) => { ) => {
/* /*
Delete a user-created category Delete a user-created category
@@ -149,10 +149,10 @@ export const annotationDeleteCategoryAction = (categoryName) => (
}; };
export const annotationCreateLabelInCategory = ( export const annotationCreateLabelInCategory = (
categoryName, categoryName: any,
labelName, labelName: any,
assignSelected assignSelected: any
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
/* /*
Add a new label to a user-defined category. If assignSelected is true, assign Add a new label to a user-defined category. If assignSelected is true, assign
the label to all currently selected cells. the label to all currently selected cells.
@@ -188,9 +188,9 @@ export const annotationCreateLabelInCategory = (
}; };
export const annotationDeleteLabelFromCategory = ( export const annotationDeleteLabelFromCategory = (
categoryName, categoryName: any,
labelName labelName: any
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
/* /*
delete a label from a user-defined category delete a label from a user-defined category
*/ */
@@ -218,10 +218,10 @@ export const annotationDeleteLabelFromCategory = (
}; };
export const annotationRenameLabelInCategory = ( export const annotationRenameLabelInCategory = (
categoryName, categoryName: any,
oldLabelName, oldLabelName: any,
newLabelName newLabelName: any
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
/* /*
label name change label name change
*/ */
@@ -255,9 +255,9 @@ export const annotationRenameLabelInCategory = (
}; };
export const annotationLabelCurrentSelection = ( export const annotationLabelCurrentSelection = (
categoryName, categoryName: any,
labelName labelName: any
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
/* /*
set the label on all currently selected set the label on all currently selected
*/ */
@@ -284,13 +284,16 @@ export const annotationLabelCurrentSelection = (
}); });
}; };
function writableAnnotations(annoMatrix) { function writableAnnotations(annoMatrix: any) {
return annoMatrix.schema.annotations.obs.columns return annoMatrix.schema.annotations.obs.columns
.filter((s) => s.writable) .filter((s: any) => s.writable)
.map((s) => s.name); .map((s: any) => s.name);
} }
export const needToSaveObsAnnotations = (annoMatrix, lastSavedAnnoMatrix) => { export const needToSaveObsAnnotations = (
annoMatrix: any,
lastSavedAnnoMatrix: any
) => {
/* /*
Return true if there are LIKELY user-defined annotation modifications between the two Return true if there are LIKELY user-defined annotation modifications between the two
annoMatrices. Technically not an action creator, but intimately intertwined annoMatrices. Technically not an action creator, but intimately intertwined
@@ -314,11 +317,14 @@ export const needToSaveObsAnnotations = (annoMatrix, lastSavedAnnoMatrix) => {
// no schema changes; check for change in contents // no schema changes; check for change in contents
return currentWritable.some( return currentWritable.some(
(col) => annoMatrix.col(col) !== lastSavedAnnoMatrix.col(col) (col: any) => annoMatrix.col(col) !== lastSavedAnnoMatrix.col(col)
); );
}; };
export const saveObsAnnotationsAction = () => async (dispatch, getState) => { export const saveObsAnnotationsAction = () => async (
dispatch: any,
getState: any
) => {
/* /*
Save the user-created obs annotations IF any have changed. Save the user-created obs annotations IF any have changed.
*/ */
@@ -388,7 +394,10 @@ export const saveObsAnnotationsAction = () => async (dispatch, getState) => {
} }
}; };
export const saveGenesetsAction = () => async (dispatch, getState) => { export const saveGenesetsAction = () => async (
dispatch: any,
getState: any
) => {
const state = getState(); const state = getState();
// bail if gene sets not available, or in readonly mode. // bail if gene sets not available, or in readonly mode.
@@ -465,7 +474,7 @@ export const saveGenesetsAction = () => async (dispatch, getState) => {
res, res,
}); });
} }
return Promise.all([ return await Promise.all([
dispatch({ dispatch({
type: "autosave: genesets complete", type: "autosave: genesets complete",
lastSavedGenesets: genesets, lastSavedGenesets: genesets,
@@ -6,9 +6,9 @@ import { AnnoMatrixObsCrossfilter } from "../annoMatrix";
import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers"; import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers";
export async function _switchEmbedding( export async function _switchEmbedding(
prevAnnoMatrix, prevAnnoMatrix: any,
prevCrossfilter, prevCrossfilter: any,
newEmbeddingName newEmbeddingName: any
) { ) {
/* /*
DRY helper used by embedding action creators DRY helper used by embedding action creators
@@ -25,9 +25,9 @@ export async function _switchEmbedding(
return [annoMatrix, obsCrossfilter]; return [annoMatrix, obsCrossfilter];
} }
export const layoutChoiceAction = (newLayoutChoice) => async ( export const layoutChoiceAction = (newLayoutChoice: any) => async (
dispatch, dispatch: any,
getState getState: any
) => { ) => {
/* /*
On layout choice, make sure we have selected all on the previous layout, AND the new On layout choice, make sure we have selected all on the previous layout, AND the new
@@ -21,7 +21,10 @@ The behavior manifest in these action creators:
Note that crossfilter indices are lazy created, as needed. Note that crossfilter indices are lazy created, as needed.
*/ */
export const genesetDelete = (genesetName) => (dispatch, getState) => { export const genesetDelete = (genesetName: any) => (
dispatch: any,
getState: any
) => {
const state = getState(); const state = getState();
const { genesets } = state; const { genesets } = state;
const gs = genesets?.genesets?.get(genesetName) ?? {}; const gs = genesets?.genesets?.get(genesetName) ?? {};
@@ -40,9 +43,9 @@ export const genesetDelete = (genesetName) => (dispatch, getState) => {
}); });
}; };
export const genesetAddGenes = (genesetName, genes) => async ( export const genesetAddGenes = (genesetName: any, genes: any) => async (
dispatch, dispatch: any,
getState getState: any
) => { ) => {
const state = getState(); const state = getState();
const { obsCrossfilter: prevObsCrossfilter, annoMatrix } = state; const { obsCrossfilter: prevObsCrossfilter, annoMatrix } = state;
@@ -50,7 +53,7 @@ export const genesetAddGenes = (genesetName, genes) => async (
const varIndex = schema.annotations.var.index; const varIndex = schema.annotations.var.index;
const df = await annoMatrix.fetch("var", varIndex); const df = await annoMatrix.fetch("var", varIndex);
const geneNames = df.col(varIndex).asArray(); const geneNames = df.col(varIndex).asArray();
genes = genes.reduce((acc, gene) => { genes = genes.reduce((acc: any, gene: any) => {
if (geneNames.indexOf(gene.geneSymbol) === -1) { if (geneNames.indexOf(gene.geneSymbol) === -1) {
postUserErrorToast( postUserErrorToast(
`${gene.geneSymbol} doesn't appear to be a valid gene name.` `${gene.geneSymbol} doesn't appear to be a valid gene name.`
@@ -78,9 +81,9 @@ export const genesetAddGenes = (genesetName, genes) => async (
}); });
}; };
export const genesetDeleteGenes = (genesetName, geneSymbols) => ( export const genesetDeleteGenes = (genesetName: any, geneSymbols: any) => (
dispatch, dispatch: any,
getState getState: any
) => { ) => {
const state = getState(); const state = getState();
const obsCrossfilter = dropGeneset(dispatch, state, genesetName, geneSymbols); const obsCrossfilter = dropGeneset(dispatch, state, genesetName, geneSymbols);
@@ -97,7 +100,11 @@ export const genesetDeleteGenes = (genesetName, geneSymbols) => (
Private Private
*/ */
function dropGenesetSummaryDimension(obsCrossfilter, state, genesetName) { function dropGenesetSummaryDimension(
obsCrossfilter: any,
state: any,
genesetName: any
) {
const { annoMatrix, genesets } = state; const { annoMatrix, genesets } = state;
const varIndex = annoMatrix.schema.annotations?.var?.index; const varIndex = annoMatrix.schema.annotations?.var?.index;
const gs = genesets?.genesets?.get(genesetName) ?? {}; const gs = genesets?.genesets?.get(genesetName) ?? {};
@@ -113,7 +120,7 @@ function dropGenesetSummaryDimension(obsCrossfilter, state, genesetName) {
return obsCrossfilter.dropDimension("X", query); return obsCrossfilter.dropDimension("X", query);
} }
function dropGeneDimension(obsCrossfilter, state, gene) { function dropGeneDimension(obsCrossfilter: any, state: any, gene: any) {
const { annoMatrix } = state; const { annoMatrix } = state;
const varIndex = annoMatrix.schema.annotations?.var?.index; const varIndex = annoMatrix.schema.annotations?.var?.index;
const query = { const query = {
@@ -126,10 +133,16 @@ function dropGeneDimension(obsCrossfilter, state, gene) {
return obsCrossfilter.dropDimension("X", query); return obsCrossfilter.dropDimension("X", query);
} }
function dropGeneset(dispatch, state, genesetName, geneSymbols) { function dropGeneset(
dispatch: any,
state: any,
genesetName: any,
geneSymbols: any
) {
const { obsCrossfilter: prevObsCrossfilter } = state; const { obsCrossfilter: prevObsCrossfilter } = state;
const obsCrossfilter = geneSymbols.reduce( const obsCrossfilter = geneSymbols.reduce(
(crossfilter, gene) => dropGeneDimension(crossfilter, state, gene), (crossfilter: any, gene: any) =>
dropGeneDimension(crossfilter, state, gene),
dropGenesetSummaryDimension(prevObsCrossfilter, state, genesetName) dropGenesetSummaryDimension(prevObsCrossfilter, state, genesetName)
); );
dispatch({ dispatch({
@@ -137,7 +150,7 @@ function dropGeneset(dispatch, state, genesetName, geneSymbols) {
continuousNamespace: { isGeneSetSummary: true }, continuousNamespace: { isGeneSetSummary: true },
selection: genesetName, selection: genesetName,
}); });
geneSymbols.forEach((g) => geneSymbols.forEach((g: any) =>
dispatch({ dispatch({
type: "continuous metadata histogram cancel", type: "continuous metadata histogram cancel",
continuousNamespace: { isUserDefined: true }, continuousNamespace: { isUserDefined: true },
@@ -15,7 +15,7 @@ import * as genesetActions from "./geneset";
/* /*
return promise fetching user-configured colors return promise fetching user-configured colors
*/ */
async function userColorsFetchAndLoad(dispatch) { async function userColorsFetchAndLoad(dispatch: any) {
return fetchJson("colors").then((response) => return fetchJson("colors").then((response) =>
dispatch({ dispatch({
type: "universe: user color load success", type: "universe: user color load success",
@@ -28,7 +28,7 @@ async function schemaFetch() {
return fetchJson("schema"); return fetchJson("schema");
} }
async function configFetch(dispatch) { async function configFetch(dispatch: any) {
return fetchJson("config").then((response) => { return fetchJson("config").then((response) => {
const config = { ...globals.configDefaults, ...response.config }; const config = { ...globals.configDefaults, ...response.config };
dispatch({ dispatch({
@@ -39,7 +39,7 @@ async function configFetch(dispatch) {
}); });
} }
async function userInfoFetch(dispatch) { async function userInfoFetch(dispatch: any) {
return fetchJson("userinfo").then((response) => { return fetchJson("userinfo").then((response) => {
const { userinfo: userInfo } = response || {}; const { userinfo: userInfo } = response || {};
dispatch({ dispatch({
@@ -50,7 +50,7 @@ async function userInfoFetch(dispatch) {
}); });
} }
async function genesetsFetch(dispatch, config) { async function genesetsFetch(dispatch: any, config: any) {
/* request genesets ONLY if the backend supports the feature */ /* request genesets ONLY if the backend supports the feature */
const defaultResponse = { const defaultResponse = {
genesets: [], genesets: [],
@@ -71,25 +71,26 @@ async function genesetsFetch(dispatch, config) {
} }
} }
function prefetchEmbeddings(annoMatrix) { function prefetchEmbeddings(annoMatrix: any) {
/* /*
prefetch requests for all embeddings prefetch requests for all embeddings
*/ */
const { schema } = annoMatrix; const { schema } = annoMatrix;
const available = schema.layout.obs.map((v) => v.name); const available = schema.layout.obs.map((v: any) => v.name);
available.forEach((embName) => annoMatrix.prefetch("emb", embName)); available.forEach((embName: any) => annoMatrix.prefetch("emb", embName));
} }
/* /*
Application bootstrap Application bootstrap
*/ */
const doInitialDataLoad = () => const doInitialDataLoad = () =>
catchErrorsWrap(async (dispatch) => { catchErrorsWrap(async (dispatch: any) => {
dispatch({ type: "initial data load start" }); dispatch({ type: "initial data load start" });
try { try {
const [config, schema] = await Promise.all([ const [config, schema] = await Promise.all([
configFetch(dispatch), configFetch(dispatch),
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
schemaFetch(dispatch), schemaFetch(dispatch),
userColorsFetchAndLoad(dispatch), userColorsFetchAndLoad(dispatch),
userInfoFetch(dispatch), userInfoFetch(dispatch),
@@ -113,7 +114,7 @@ const doInitialDataLoad = () =>
const layoutSchema = schema?.schema?.layout?.obs ?? []; const layoutSchema = schema?.schema?.layout?.obs ?? [];
if ( if (
defaultEmbedding && defaultEmbedding &&
layoutSchema.some((s) => s.name === defaultEmbedding) layoutSchema.some((s: any) => s.name === defaultEmbedding)
) { ) {
dispatch(embActions.layoutChoiceAction(defaultEmbedding)); dispatch(embActions.layoutChoiceAction(defaultEmbedding));
} }
@@ -122,21 +123,22 @@ const doInitialDataLoad = () =>
} }
}, true); }, true);
function requestSingleGeneExpressionCountsForColoringPOST(gene) { function requestSingleGeneExpressionCountsForColoringPOST(gene: any) {
return { return {
type: "color by expression", type: "color by expression",
gene, gene,
}; };
} }
const requestUserDefinedGene = (gene) => ({ const requestUserDefinedGene = (gene: any) => ({
type: "request user defined gene success", type: "request user defined gene success",
data: { data: {
genes: [gene], genes: [gene],
}, },
}); });
const dispatchDiffExpErrors = (dispatch, response) => { const dispatchDiffExpErrors = (dispatch: any, response: any) => {
switch (response.status) { switch (response.status) {
case 403: case 403:
dispatchNetworkErrorMessageToUser( dispatchNetworkErrorMessageToUser(
@@ -159,10 +161,11 @@ const dispatchDiffExpErrors = (dispatch, response) => {
} }
}; };
const requestDifferentialExpression = (set1, set2, num_genes = 50) => async ( const requestDifferentialExpression = (
dispatch, set1: any,
getState set2: any,
) => { num_genes = 50
) => async (dispatch: any, getState: any) => {
dispatch({ type: "request differential expression started" }); dispatch({ type: "request differential expression started" });
try { try {
/* /*
@@ -210,7 +213,8 @@ const requestDifferentialExpression = (set1, set2, num_genes = 50) => async (
const varIndex = await annoMatrix.fetch("var", varIndexName); const varIndex = await annoMatrix.fetch("var", varIndexName);
const diffexpLists = { negative: [], positive: [] }; const diffexpLists = { negative: [], positive: [] };
for (const polarity of Object.keys(diffexpLists)) { for (const polarity of Object.keys(diffexpLists)) {
diffexpLists[polarity] = response[polarity].map((v) => [ // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
diffexpLists[polarity] = response[polarity].map((v: any) => [
varIndex.at(v[0], varIndexName), varIndex.at(v[0], varIndexName),
...v.slice(1), ...v.slice(1),
]); ]);
@@ -229,7 +233,7 @@ const requestDifferentialExpression = (set1, set2, num_genes = 50) => async (
} }
}; };
function fetchJson(pathAndQuery) { function fetchJson(pathAndQuery: any) {
return doJsonRequest( return doJsonRequest(
`${globals.API.prefix}${globals.API.version}${pathAndQuery}` `${globals.API.prefix}${globals.API.version}${pathAndQuery}`
); );
@@ -2,11 +2,11 @@
Action creators for selection Action creators for selection
*/ */
export const selectContinuousMetadataAction = ( export const selectContinuousMetadataAction = (
type, type: any,
query, query: any,
range, range: any,
oldProps = {} oldProps = {}
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
const { obsCrossfilter: prevObsCrossfilter } = getState(); const { obsCrossfilter: prevObsCrossfilter } = getState();
const selection = range const selection = range
@@ -29,13 +29,13 @@ export const selectContinuousMetadataAction = (
}; };
export const selectCategoricalMetadataAction = ( export const selectCategoricalMetadataAction = (
type, // action type type: any, // action type
metadataField, // annotation category name metadataField: any, // annotation category name
labels, labels: any,
label, // the label being selected/deselected label: any, // the label being selected/deselected
isSelected, // bool isSelected: any, // bool
oldProps = {} oldProps = {}
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
const { const {
obsCrossfilter: prevObsCrossfilter, obsCrossfilter: prevObsCrossfilter,
categoricalSelection, categoricalSelection,
@@ -43,7 +43,7 @@ export const selectCategoricalMetadataAction = (
const labelSelectionState = new Map(categoricalSelection[metadataField]); const labelSelectionState = new Map(categoricalSelection[metadataField]);
labels.forEach( labels.forEach(
(l) => labelSelectionState.has(l) || labelSelectionState.set(l, true) (l: any) => labelSelectionState.has(l) || labelSelectionState.set(l, true)
); );
labelSelectionState.set(label, isSelected); labelSelectionState.set(label, isSelected);
@@ -70,19 +70,19 @@ export const selectCategoricalMetadataAction = (
}; };
export const selectCategoricalAllMetadataAction = ( export const selectCategoricalAllMetadataAction = (
type, // action type type: any, // action type
metadataField, // annotation category name metadataField: any, // annotation category name
labels, labels: any,
isSelected, // bool, select all or none isSelected: any, // bool, select all or none
oldProps = {} oldProps = {}
) => async (dispatch, getState) => { ) => async (dispatch: any, getState: any) => {
const { const {
obsCrossfilter: prevObsCrossfilter, obsCrossfilter: prevObsCrossfilter,
categoricalSelection, categoricalSelection,
} = getState(); } = getState();
const labelSelectionState = new Map(categoricalSelection[metadataField]); const labelSelectionState = new Map(categoricalSelection[metadataField]);
labels.forEach((label) => labelSelectionState.set(label, isSelected)); labels.forEach((label: any) => labelSelectionState.set(label, isSelected));
const selection = { mode: isSelected ? "all" : "none" }; const selection = { mode: isSelected ? "all" : "none" };
const obsCrossfilter = await prevObsCrossfilter.select( const obsCrossfilter = await prevObsCrossfilter.select(
@@ -108,10 +108,11 @@ export const graphBrushStartAction = () =>
/* no change to crossfilter until a change fires */ /* no change to crossfilter until a change fires */
({ type: "graph brush start" }); ({ type: "graph brush start" });
const _graphBrushWithinRectAction = (type, embName, brushCoords) => async ( const _graphBrushWithinRectAction = (
dispatch, type: any,
getState embName: any,
) => { brushCoords: any
) => async (dispatch: any, getState: any) => {
const { obsCrossfilter: prevObsCrossfilter } = getState(); const { obsCrossfilter: prevObsCrossfilter } = getState();
const selection = { mode: "within-rect", ...brushCoords }; const selection = { mode: "within-rect", ...brushCoords };
@@ -128,7 +129,10 @@ const _graphBrushWithinRectAction = (type, embName, brushCoords) => async (
}); });
}; };
const _graphAllAction = (type, embName) => async (dispatch, getState) => { const _graphAllAction = (type: any, embName: any) => async (
dispatch: any,
getState: any
) => {
const { obsCrossfilter: prevObsCrossfilter } = getState(); const { obsCrossfilter: prevObsCrossfilter } = getState();
const obsCrossfilter = await prevObsCrossfilter.select("emb", embName, { const obsCrossfilter = await prevObsCrossfilter.select("emb", embName, {
@@ -141,30 +145,30 @@ const _graphAllAction = (type, embName) => async (dispatch, getState) => {
}); });
}; };
export const graphBrushChangeAction = (embName, brushCoords) => export const graphBrushChangeAction = (embName: any, brushCoords: any) =>
_graphBrushWithinRectAction("graph brush change", embName, brushCoords); _graphBrushWithinRectAction("graph brush change", embName, brushCoords);
export const graphBrushEndAction = (embName, brushCoords) => export const graphBrushEndAction = (embName: any, brushCoords: any) =>
_graphBrushWithinRectAction("graph brush end", embName, brushCoords); _graphBrushWithinRectAction("graph brush end", embName, brushCoords);
export const graphBrushCancelAction = (embName) => export const graphBrushCancelAction = (embName: any) =>
_graphAllAction("graph brush cancel", embName); _graphAllAction("graph brush cancel", embName);
export const graphBrushDeselectAction = (embName) => export const graphBrushDeselectAction = (embName: any) =>
_graphAllAction("graph brush deselect", embName); _graphAllAction("graph brush deselect", embName);
export const graphLassoStartAction = () => export const graphLassoStartAction = () =>
/* no change to crossfilter until a change fires */ /* no change to crossfilter until a change fires */
({ type: "graph lasso start" }); ({ type: "graph lasso start" });
export const graphLassoCancelAction = (embName) => export const graphLassoCancelAction = (embName: any) =>
_graphAllAction("graph lasso cancel", embName); _graphAllAction("graph lasso cancel", embName);
export const graphLassoDeselectAction = (embName) => export const graphLassoDeselectAction = (embName: any) =>
_graphAllAction("graph lasso cancel", embName); _graphAllAction("graph lasso cancel", embName);
export const graphLassoEndAction = (embName, polygon) => async ( export const graphLassoEndAction = (embName: any, polygon: any) => async (
dispatch, dispatch: any,
getState getState: any
) => { ) => {
const { obsCrossfilter: prevObsCrossfilter } = getState(); const { obsCrossfilter: prevObsCrossfilter } = getState();
@@ -188,7 +192,10 @@ export const graphLassoEndAction = (embName, polygon) => async (
/* /*
Differential expression set selection Differential expression set selection
*/ */
export const setCellSetFromSelection = (cellSetId) => (dispatch, getState) => { export const setCellSetFromSelection = (cellSetId: any) => (
dispatch: any,
getState: any
) => {
const { obsCrossfilter } = getState(); const { obsCrossfilter } = getState();
const selected = obsCrossfilter.allSelectedLabels(); const selected = obsCrossfilter.allSelectedLabels();
@@ -18,7 +18,10 @@ import {
_userResetSubsetAnnoMatrix, _userResetSubsetAnnoMatrix,
} from "../util/stateManager/viewStackHelpers"; } from "../util/stateManager/viewStackHelpers";
export const clipAction = (min, max) => (dispatch, getState) => { export const clipAction = (min: any, max: any) => (
dispatch: any,
getState: any
) => {
/* /*
apply a clip to the current annoMatrix. By convention, the clip apply a clip to the current annoMatrix. By convention, the clip
view is ALWAYS the top view. view is ALWAYS the top view.
@@ -34,7 +37,7 @@ export const clipAction = (min, max) => (dispatch, getState) => {
}); });
}; };
export const subsetAction = () => (dispatch, getState) => { export const subsetAction = () => (dispatch: any, getState: any) => {
/* /*
Subset the annoMatrix to the current crossfilter selection by pushing a Subset the annoMatrix to the current crossfilter selection by pushing a
subset view. subset view.
@@ -58,7 +61,7 @@ export const subsetAction = () => (dispatch, getState) => {
}); });
}; };
export const resetSubsetAction = () => (dispatch, getState) => { export const resetSubsetAction = () => (dispatch: any, getState: any) => {
/* /*
Reset the annoMatrix to all data. Because we may have multiple views Reset the annoMatrix to all data. Because we may have multiple views
stacked, we pop them all. By convention, any clip transformation will stacked, we pop them all. By convention, any clip transformation will
@@ -17,6 +17,28 @@ import { _queryValidate, _queryCacheKey } from "./query";
const _dataframeCache = dataframeMemo(128); const _dataframeCache = dataframeMemo(128);
export default class AnnoMatrix { export default class AnnoMatrix {
public isView: any;
public nObs: any;
public nVar: any;
public rowIndex: any;
public schema: any;
public userFlags: any;
public viewOf: any;
protected _cache: any;
private _pendingLoad: any;
private _whereCache: any;
private _gcInfo: any;
/* /*
Abstract base class for all AnnoMatrix objects. This class provides a proxy Abstract base class for all AnnoMatrix objects. This class provides a proxy
to the annotated matrix data authoritatively served by the server/back-end. to the annotated matrix data authoritatively served by the server/back-end.
@@ -54,7 +76,7 @@ export default class AnnoMatrix {
return ["obs", "var", "emb", "X"]; return ["obs", "var", "emb", "X"];
} }
constructor(schema, nObs, nVar, rowIndex = null) { constructor(schema: any, nObs: any, nVar: any, rowIndex = null) {
/* /*
Private constructor - this is an abstract base class. Do not use. Private constructor - this is an abstract base class. Do not use.
*/ */
@@ -83,13 +105,13 @@ export default class AnnoMatrix {
this.userFlags = {}; this.userFlags = {};
/* /*
Private instance variables. Private instance variables.
These are caches - lazily loaded. The only guarantee is that if they These are caches - lazily loaded. The only guarantee is that if they
are loaded, they will conform to the schema & dimensionality constraints. are loaded, they will conform to the schema & dimensionality constraints.
Do NOT use directly - instead, use the fetch() and preload() API. Do NOT use directly - instead, use the fetch() and preload() API.
*/ */
this._cache = { this._cache = {
obs: Dataframe.empty(this.rowIndex), obs: Dataframe.empty(this.rowIndex),
var: Dataframe.empty(this.rowIndex), var: Dataframe.empty(this.rowIndex),
@@ -109,6 +131,7 @@ export default class AnnoMatrix {
/** /**
** Schema helper/accessors ** Schema helper/accessors
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
getMatrixColumns(field) { getMatrixColumns(field) {
/* /*
Return array of column names in the field. ONLY supported on the Return array of column names in the field. ONLY supported on the
@@ -132,6 +155,7 @@ export default class AnnoMatrix {
return AnnoMatrix.fields(); return AnnoMatrix.fields();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
getColumnSchema(field, col) { getColumnSchema(field, col) {
/* /*
Return the schema for the field & column ,eg, Return the schema for the field & column ,eg,
@@ -144,6 +168,7 @@ export default class AnnoMatrix {
return _getColumnSchema(this.schema, field, col); return _getColumnSchema(this.schema, field, col);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
getColumnDimensions(field, col) { getColumnDimensions(field, col) {
/* /*
Return the dimensions on this field / column. For most fields, which are 1D, Return the dimensions on this field / column. For most fields, which are 1D,
@@ -174,6 +199,7 @@ export default class AnnoMatrix {
/** /**
** Load / read interfaces ** Load / read interfaces
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
fetch(field, q) { fetch(field, q) {
/* /*
Return the given query on a single matrix field as a single dataframe. Return the given query on a single matrix field as a single dataframe.
@@ -231,6 +257,7 @@ export default class AnnoMatrix {
return this._fetch(field, q); return this._fetch(field, q);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
prefetch(field, q) { prefetch(field, q) {
/* /*
Start a data fetch & cache fill. Identical to fetch() except it does Start a data fetch & cache fill. Identical to fetch() except it does
@@ -261,7 +288,8 @@ export default class AnnoMatrix {
** The actual implementation is in the sub-classes, which MUST override these. ** The actual implementation is in the sub-classes, which MUST override these.
**/ **/
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
addObsAnnoCategory(col, category) { addObsAnnoCategory(col, category) {
/* /*
Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix. Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix.
@@ -278,7 +306,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
async removeObsAnnoCategory(col, category, unassignedCategory) { async removeObsAnnoCategory(col, category, unassignedCategory) {
/* /*
Remove a category value from an obs column, reassign any obs having that value Remove a category value from an obs column, reassign any obs having that value
@@ -299,7 +328,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
dropObsColumn(col) { dropObsColumn(col) {
/* /*
Drop an entire writable column, eg a user-created obs annotation. Typical use Drop an entire writable column, eg a user-created obs annotation. Typical use
@@ -315,7 +345,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'colSchema' is declared but its value is never rea... Remove this comment to see the full error message
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
addObsColumn(colSchema, Ctor, value) { addObsColumn(colSchema, Ctor, value) {
/* /*
Add a new writable OBS annotation column, with the caller-specified schema, initial value Add a new writable OBS annotation column, with the caller-specified schema, initial value
@@ -344,7 +375,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'oldCol' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
renameObsColumn(oldCol, newCol) { renameObsColumn(oldCol, newCol) {
/* /*
Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix. Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix.
@@ -359,7 +391,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
async setObsColumnValues(col, obsLabels, value) { async setObsColumnValues(col, obsLabels, value) {
/* /*
Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be
@@ -377,7 +410,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
async resetObsColumnValues(col, oldValue, newValue) { async resetObsColumnValues(col, oldValue, newValue) {
/* /*
Set by value - all elements in the column with value 'oldValue' are set to 'newValue'. Set by value - all elements in the column with value 'oldValue' are set to 'newValue'.
@@ -394,7 +428,8 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements // @ts-expect-error ts-migrate(6133) FIXME: 'colSchema' is declared but its value is never rea... Remove this comment to see the full error message
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars -- make sure subclass implements
addEmbedding(colSchema) { addEmbedding(colSchema) {
/* /*
Add a new obs embedding to the AnnoMatrix, with provided schema. Add a new obs embedding to the AnnoMatrix, with provided schema.
@@ -407,28 +442,35 @@ export default class AnnoMatrix {
_subclassResponsibility(); _subclassResponsibility();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
getCacheKeys(field, query) { getCacheKeys(field, query) {
/* /*
Return cache keys for columns associated with this query. May return Return cache keys for columns associated with this query. May return
[unknown] if no keys are known (ie, nothing is or was cached). [unknown] if no keys are known (ie, nothing is or was cached).
*/ */
return _whereCacheGet(this._whereCache, this.schema, field, query); return _whereCacheGet(this._whereCache, this.schema, field, query);
} }
/** /**
** Private interfaces below. ** Private interfaces below.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_resolveCachedQueries(field, queries) { _resolveCachedQueries(field, queries) {
return queries return (
.map((query) => queries
_whereCacheGet(this._whereCache, this.schema, field, query).filter( // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'query' implicitly has an 'any' type.
(cacheKey) => .map((query) =>
cacheKey !== undefined && this._cache[field].hasCol(cacheKey) _whereCacheGet(this._whereCache, this.schema, field, query).filter(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'cacheKey' implicitly has an 'any' type.
(cacheKey) =>
cacheKey !== undefined && this._cache[field].hasCol(cacheKey)
)
) )
) .flat()
.flat(); );
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
async _fetch(field, q) { async _fetch(field, q) {
if (!AnnoMatrix.fields().includes(field)) return undefined; if (!AnnoMatrix.fields().includes(field)) return undefined;
const queries = Array.isArray(q) ? q : [q]; const queries = Array.isArray(q) ? q : [q];
@@ -441,6 +483,7 @@ export default class AnnoMatrix {
/* find any query not already cached */ /* find any query not already cached */
const uncachedQueries = queries.filter((query) => const uncachedQueries = queries.filter((query) =>
_whereCacheGet(this._whereCache, this.schema, field, query).some( _whereCacheGet(this._whereCache, this.schema, field, query).some(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'cacheKey' implicitly has an 'any' type.
(cacheKey) => (cacheKey) =>
cacheKey === undefined || !this._cache[field].hasCol(cacheKey) cacheKey === undefined || !this._cache[field].hasCol(cacheKey)
) )
@@ -450,8 +493,10 @@ export default class AnnoMatrix {
if (uncachedQueries.length > 0) { if (uncachedQueries.length > 0) {
await Promise.all( await Promise.all(
uncachedQueries.map((query) => uncachedQueries.map((query) =>
// @ts-expect-error ts-migrate(7006) FIXME: Parameter '_field' implicitly has an 'any' type.
this._getPendingLoad(field, query, async (_field, _query) => { this._getPendingLoad(field, query, async (_field, _query) => {
/* fetch, then index. _doLoad is subclass interface */ /* fetch, then index. _doLoad is subclass interface */
// @ts-expect-error ts-migrate(2488) FIXME: Type 'void' must have a '[Symbol.iterator]()' meth... Remove this comment to see the full error message
const [whereCacheUpdate, df] = await this._doLoad(_field, _query); const [whereCacheUpdate, df] = await this._doLoad(_field, _query);
this._cache[_field] = this._cache[_field].withColsFrom(df); this._cache[_field] = this._cache[_field].withColsFrom(df);
this._whereCache = _whereCacheMerge( this._whereCache = _whereCacheMerge(
@@ -472,6 +517,7 @@ export default class AnnoMatrix {
return response; return response;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
async _getPendingLoad(field, query, fetchFn) { async _getPendingLoad(field, query, fetchFn) {
/* /*
Given a query on a field, ensure that we only have a single outstanding Given a query on a field, ensure that we only have a single outstanding
@@ -527,19 +573,21 @@ export default class AnnoMatrix {
To be effective, the GC callback needs to be invoked from the undo/redo code, To be effective, the GC callback needs to be invoked from the undo/redo code,
as much of the cache is pinned by that data structure. as much of the cache is pinned by that data structure.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_gcField(field, isHot, pinnedColumns) { _gcField(field, isHot, pinnedColumns) {
const maxColumns = isHot ? 256 : 10; // maybe to aggressive? const maxColumns = isHot ? 256 : 10;
const cache = this._cache[field]; const cache = this._cache[field];
if (cache.colIndex.size() < maxColumns) return; // trivial rejection if (cache.colIndex.size() < maxColumns) return; // trivial rejection
const candidates = cache.colIndex const candidates = cache.colIndex
.labels() .labels()
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
.filter((col) => !pinnedColumns.includes(col)); .filter((col) => !pinnedColumns.includes(col));
const excessCount = candidates.length + pinnedColumns.length - maxColumns; const excessCount = candidates.length + pinnedColumns.length - maxColumns;
if (excessCount > 0) { if (excessCount > 0) {
const { _gcInfo } = this; const { _gcInfo } = this;
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'a' implicitly has an 'any' type.
candidates.sort((a, b) => { candidates.sort((a, b) => {
let atime = _gcInfo.get(_columnCacheKey(field, a)); let atime = _gcInfo.get(_columnCacheKey(field, a));
if (atime === undefined) atime = 0; if (atime === undefined) atime = 0;
@@ -558,13 +606,16 @@ export default class AnnoMatrix {
// )}]` // )}]`
// ); // );
this._cache[field] = toDrop.reduce( this._cache[field] = toDrop.reduce(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type.
(df, col) => df.dropCol(col), (df, col) => df.dropCol(col),
this._cache[field] this._cache[field]
); );
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
toDrop.forEach((col) => _gcInfo.delete(_columnCacheKey(field, col))); toDrop.forEach((col) => _gcInfo.delete(_columnCacheKey(field, col)));
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_gcFetchCleanup(field, pinnedColumns) { _gcFetchCleanup(field, pinnedColumns) {
/* /*
Called during data load/fetch. By definition, this is 'hot', so we Called during data load/fetch. By definition, this is 'hot', so we
@@ -579,6 +630,7 @@ export default class AnnoMatrix {
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'hints' implicitly has an 'any' type.
_gc(hints) { _gc(hints) {
/* /*
Called from middleware, or elsewhere. isHot is true if we are in the active store, Called from middleware, or elsewhere. isHot is true if we are in the active store,
@@ -591,6 +643,7 @@ export default class AnnoMatrix {
); );
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_gcUpdateStats(field, dataframe) { _gcUpdateStats(field, dataframe) {
/* /*
called each time a query is performed, allowing the gc to update any bookkeeping called each time a query is performed, allowing the gc to update any bookkeeping
@@ -600,6 +653,7 @@ export default class AnnoMatrix {
const cols = dataframe.colIndex.labels(); const cols = dataframe.colIndex.labels();
const { _gcInfo } = this; const { _gcInfo } = this;
const now = Date.now(); const now = Date.now();
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'c' implicitly has an 'any' type.
cols.forEach((c) => { cols.forEach((c) => {
_gcInfo.set(_columnCacheKey(field, c), now); _gcInfo.set(_columnCacheKey(field, c), now);
}); });
@@ -617,6 +671,7 @@ export default class AnnoMatrix {
Do not override _clone(); Do not override _clone();
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'clone' implicitly has an 'any' type.
_cloneDeeper(clone) { _cloneDeeper(clone) {
clone._cache = _shallowClone(this._cache); clone._cache = _shallowClone(this._cache);
clone._gcInfo = new Map(); clone._gcInfo = new Map();
@@ -640,6 +695,7 @@ export default class AnnoMatrix {
/* /*
private utility functions below private utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
function _columnCacheKey(field, column) { function _columnCacheKey(field, column) {
return `${field}/${column}`; return `${field}/${column}`;
} }
@@ -1,6 +1,6 @@
/* /*
Shallow clone an object, correctly handling prototype Shallow clone an object, correctly handling prototype
*/ */
export default function _shallowClone(orig) { export default function _shallowClone(orig: any) {
return Object.assign(Object.create(Object.getPrototypeOf(orig)), orig); return Object.assign(Object.create(Object.getPrototypeOf(orig)), orig);
} }
@@ -10,26 +10,31 @@ AnnoMatrix stay in sync:
import Crossfilter from "../util/typedCrossfilter"; import Crossfilter from "../util/typedCrossfilter";
import { _getColumnSchema } from "./schema"; import { _getColumnSchema } from "./schema";
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
function _dimensionNameFromDf(field, df) { function _dimensionNameFromDf(field, df) {
const colNames = df.colIndex.labels(); const colNames = df.colIndex.labels();
return _dimensionName(field, colNames); return _dimensionName(field, colNames);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
function _dimensionName(field, colNames) { function _dimensionName(field, colNames) {
if (!Array.isArray(colNames)) return `${field}/${colNames}`; if (!Array.isArray(colNames)) return `${field}/${colNames}`;
return `${field}/${colNames.join(":")}`; return `${field}/${colNames.join(":")}`;
} }
export default class AnnoMatrixObsCrossfilter { export default class AnnoMatrixObsCrossfilter {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
constructor(annoMatrix, _obsCrossfilter = null) { constructor(annoMatrix, _obsCrossfilter = null) {
this.annoMatrix = annoMatrix; (this as any).annoMatrix = annoMatrix;
this.obsCrossfilter = (this as any).obsCrossfilter =
_obsCrossfilter || new Crossfilter(annoMatrix._cache.obs); _obsCrossfilter || new Crossfilter(annoMatrix._cache.obs);
this.obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs); (this as any).obsCrossfilter = (this as any).obsCrossfilter.setData(
annoMatrix._cache.obs
);
} }
size() { size() {
return this.obsCrossfilter.size(); return (this as any).obsCrossfilter.size();
} }
/** /**
@@ -39,14 +44,23 @@ export default class AnnoMatrixObsCrossfilter {
See API documentation in annoMatrix.js. See API documentation in annoMatrix.js.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
addObsColumn(colSchema, Ctor, value) { addObsColumn(colSchema, Ctor, value) {
const annoMatrix = this.annoMatrix.addObsColumn(colSchema, Ctor, value); const annoMatrix = (this as any).annoMatrix.addObsColumn(
const obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs); colSchema,
Ctor,
value
);
const obsCrossfilter = (this as any).obsCrossfilter.setData(
annoMatrix._cache.obs
);
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
dropObsColumn(col) { dropObsColumn(col) {
const annoMatrix = this.annoMatrix.dropObsColumn(col); const annoMatrix = (this as any).annoMatrix.dropObsColumn(col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
const dimName = _dimensionName("obs", col); const dimName = _dimensionName("obs", col);
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
@@ -55,10 +69,12 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'oldCol' implicitly has an 'any' type.
renameObsColumn(oldCol, newCol) { renameObsColumn(oldCol, newCol) {
const annoMatrix = this.annoMatrix.renameObsColumn(oldCol, newCol); const annoMatrix = (this as any).annoMatrix.renameObsColumn(oldCol, newCol);
const oldDimName = _dimensionName("obs", oldCol); const oldDimName = _dimensionName("obs", oldCol);
const newDimName = _dimensionName("obs", newCol); const newDimName = _dimensionName("obs", newCol);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(oldDimName)) { if (obsCrossfilter.hasDimension(oldDimName)) {
obsCrossfilter = obsCrossfilter.renameDimension(oldDimName, newDimName); obsCrossfilter = obsCrossfilter.renameDimension(oldDimName, newDimName);
@@ -66,9 +82,14 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
addObsAnnoCategory(col, category) { addObsAnnoCategory(col, category) {
const annoMatrix = this.annoMatrix.addObsAnnoCategory(col, category); const annoMatrix = (this as any).annoMatrix.addObsAnnoCategory(
col,
category
);
const dimName = _dimensionName("obs", col); const dimName = _dimensionName("obs", col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -76,13 +97,15 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
async removeObsAnnoCategory(col, category, unassignedCategory) { async removeObsAnnoCategory(col, category, unassignedCategory) {
const annoMatrix = await this.annoMatrix.removeObsAnnoCategory( const annoMatrix = await (this as any).annoMatrix.removeObsAnnoCategory(
col, col,
category, category,
unassignedCategory unassignedCategory
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName("obs", col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -90,13 +113,15 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
async setObsColumnValues(col, rowLabels, value) { async setObsColumnValues(col, rowLabels, value) {
const annoMatrix = await this.annoMatrix.setObsColumnValues( const annoMatrix = await (this as any).annoMatrix.setObsColumnValues(
col, col,
rowLabels, rowLabels,
value value
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName("obs", col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -104,13 +129,15 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
async resetObsColumnValues(col, oldValue, newValue) { async resetObsColumnValues(col, oldValue, newValue) {
const annoMatrix = await this.annoMatrix.resetObsColumnValues( const annoMatrix = await (this as any).annoMatrix.resetObsColumnValues(
col, col,
oldValue, oldValue,
newValue newValue
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName("obs", col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -118,9 +145,13 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
addEmbedding(colSchema) { addEmbedding(colSchema) {
const annoMatrix = this.annoMatrix.addEmbedding(colSchema); const annoMatrix = (this as any).annoMatrix.addEmbedding(colSchema);
return new AnnoMatrixObsCrossfilter(annoMatrix, this.obsCrossfilter); return new AnnoMatrixObsCrossfilter(
annoMatrix,
(this as any).obsCrossfilter
);
} }
/** /**
@@ -128,11 +159,15 @@ export default class AnnoMatrixObsCrossfilter {
* want to stop trackin the selection state, but aren't sure we want to blow the * want to stop trackin the selection state, but aren't sure we want to blow the
* annomatrix cache. * annomatrix cache.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
dropDimension(field, query) { dropDimension(field, query) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message
const { annoMatrix } = this; const { annoMatrix } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
const keys = annoMatrix const keys = annoMatrix
.getCacheKeys(field, query) .getCacheKeys(field, query)
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'k' implicitly has an 'any' type.
.filter((k) => k !== undefined); .filter((k) => k !== undefined);
const dimName = _dimensionName(field, keys); const dimName = _dimensionName(field, keys);
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
@@ -146,8 +181,11 @@ export default class AnnoMatrixObsCrossfilter {
are just wrappers to lazy create indices. are just wrappers to lazy create indices.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
async select(field, query, spec) { async select(field, query, spec) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message
const { annoMatrix } = this; const { annoMatrix } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (!annoMatrix?._cache?.[field]) { if (!annoMatrix?._cache?.[field]) {
@@ -180,55 +218,59 @@ export default class AnnoMatrixObsCrossfilter {
/* /*
Select all on any dimension in this field. Select all on any dimension in this field.
*/ */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message
const { annoMatrix } = this; const { annoMatrix } = this;
const currentDims = this.obsCrossfilter.dimensionNames(); const currentDims = (this as any).obsCrossfilter.dimensionNames();
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'xfltr' implicitly has an 'any' type.
const obsCrossfilter = currentDims.reduce((xfltr, dim) => { const obsCrossfilter = currentDims.reduce((xfltr, dim) => {
return xfltr.select(dim, { mode: "all" }); return xfltr.select(dim, { mode: "all" });
}, this.obsCrossfilter); }, (this as any).obsCrossfilter);
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
countSelected() { countSelected() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if (this.obsCrossfilter.size() === 0) return this.annoMatrix.nObs; if ((this as any).obsCrossfilter.size() === 0)
return this.obsCrossfilter.countSelected(); return (this as any).annoMatrix.nObs;
return (this as any).obsCrossfilter.countSelected();
} }
allSelectedMask() { allSelectedMask() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
this.obsCrossfilter.size() === 0 || (this as any).obsCrossfilter.size() === 0 ||
this.obsCrossfilter.dimensionNames().length === 0 (this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
/* fake the mask */ /* fake the mask */
return new Uint8Array(this.annoMatrix.nObs).fill(1); return new Uint8Array((this as any).annoMatrix.nObs).fill(1);
} }
return this.obsCrossfilter.allSelectedMask(); return (this as any).obsCrossfilter.allSelectedMask();
} }
allSelectedLabels() { allSelectedLabels() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
this.obsCrossfilter.size() === 0 || (this as any).obsCrossfilter.size() === 0 ||
this.obsCrossfilter.dimensionNames().length === 0 (this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
return this.annoMatrix.rowIndex.labels(); return (this as any).annoMatrix.rowIndex.labels();
} }
const mask = this.obsCrossfilter.allSelectedMask(); const mask = (this as any).obsCrossfilter.allSelectedMask();
const index = this.annoMatrix.rowIndex.isubsetMask(mask); const index = (this as any).annoMatrix.rowIndex.isubsetMask(mask);
return index.labels(); return index.labels();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'array' implicitly has an 'any' type.
fillByIsSelected(array, selectedValue, deselectedValue) { fillByIsSelected(array, selectedValue, deselectedValue) {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
this.obsCrossfilter.size() === 0 || (this as any).obsCrossfilter.size() === 0 ||
this.obsCrossfilter.dimensionNames().length === 0 (this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
return array.fill(selectedValue); return array.fill(selectedValue);
} }
return this.obsCrossfilter.fillByIsSelected( return (this as any).obsCrossfilter.fillByIsSelected(
array, array,
selectedValue, selectedValue,
deselectedValue deselectedValue
@@ -239,21 +281,29 @@ export default class AnnoMatrixObsCrossfilter {
** Private below ** Private below
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
_addObsCrossfilterDimension(annoMatrix, obsCrossfilter, field, df) { _addObsCrossfilterDimension(annoMatrix, obsCrossfilter, field, df) {
if (field === "var") return obsCrossfilter; if (field === "var") return obsCrossfilter;
const dimName = _dimensionNameFromDf(field, df); const dimName = _dimensionNameFromDf(field, df);
const dimParams = this._getObsDimensionParams(field, df); const dimParams = this._getObsDimensionParams(field, df);
obsCrossfilter = obsCrossfilter.setData(annoMatrix._cache.obs); obsCrossfilter = obsCrossfilter.setData(annoMatrix._cache.obs);
// @ts-expect-error ts-migrate(2488) FIXME: Type 'any[] | undefined' must have a '[Symbol.iter... Remove this comment to see the full error message
obsCrossfilter = obsCrossfilter.addDimension(dimName, ...dimParams); obsCrossfilter = obsCrossfilter.addDimension(dimName, ...dimParams);
return obsCrossfilter; return obsCrossfilter;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_getColumnBaseType(field, col) { _getColumnBaseType(field, col) {
/* Look up the primitive type for this field/col */ /* Look up the primitive type for this field/col */
const colSchema = _getColumnSchema(this.annoMatrix.schema, field, col); const colSchema = _getColumnSchema(
(this as any).annoMatrix.schema,
field,
col
);
return colSchema.type; return colSchema.type;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
_getObsDimensionParams(field, df) { _getObsDimensionParams(field, df) {
/* return the crossfilter dimensiontype type and params for this field/dataframe */ /* return the crossfilter dimensiontype type and params for this field/dataframe */
@@ -1,19 +1,19 @@
export { doBinaryRequest, doFetch } from "../util/actionHelpers"; export { doBinaryRequest, doFetch } from "../util/actionHelpers";
/* double URI encode - needed for query-param filters */ /* double URI encode - needed for query-param filters */
export function _dubEncURIComp(s) { export function _dubEncURIComp(s: any) {
return encodeURIComponent(encodeURIComponent(s)); return encodeURIComponent(encodeURIComponent(s));
} }
/* currently unused, consider deleting */ /* currently unused, consider deleting */
export function _fetchResult(promise) { export function _fetchResult(promise: any) {
let _status = "pending"; let _status = "pending";
const res = promise.then( const res = promise.then(
(r) => { (r: any) => {
_status = "success"; _status = "success";
return r; return r;
}, },
(e) => { (e: any) => {
_status = "error"; _status = "error";
throw e; throw e;
} }
@@ -23,6 +23,8 @@ import {
const promiseThrottle = new PromiseLimit(5); const promiseThrottle = new PromiseLimit(5);
export default class AnnoMatrixLoader extends AnnoMatrix { export default class AnnoMatrixLoader extends AnnoMatrix {
baseURL: any;
/* /*
AnnoMatrix implementation which proxies to HTTP server using the CXG REST API. AnnoMatrix implementation which proxies to HTTP server using the CXG REST API.
Used as the base (non-view) instance. Used as the base (non-view) instance.
@@ -33,7 +35,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
new AnnoMatrixLoader(serverBaseURL, schema) -> instance new AnnoMatrixLoader(serverBaseURL, schema) -> instance
*/ */
constructor(baseURL, schema) { constructor(baseURL: any, schema: any) {
const { nObs, nVar } = schema.dataframe; const { nObs, nVar } = schema.dataframe;
super(schema, nObs, nVar); super(schema, nObs, nVar);
@@ -48,7 +50,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
/** /**
** Public. API described in base class. ** Public. API described in base class.
**/ **/
addObsAnnoCategory(col, category) { addObsAnnoCategory(col: any, category: any) {
/* /*
Add a new category (aka label) to the schema for an obs column. Add a new category (aka label) to the schema for an obs column.
*/ */
@@ -60,7 +62,11 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
async removeObsAnnoCategory(col, category, unassignedCategory) { async removeObsAnnoCategory(
col: any,
category: any,
unassignedCategory: any
) {
/* /*
Remove a single "category" (aka "label") from the data & schema of an obs column. Remove a single "category" (aka "label") from the data & schema of an obs column.
*/ */
@@ -80,7 +86,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
dropObsColumn(col) { dropObsColumn(col: any) {
/* /*
drop column from field drop column from field
*/ */
@@ -88,11 +94,12 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
_writableCheck(colSchema); // throws on error _writableCheck(colSchema); // throws on error
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col); newAnnoMatrix._cache.obs = (this as any)._cache.obs.dropCol(col);
newAnnoMatrix.schema = removeObsAnnoColumn(this.schema, col); newAnnoMatrix.schema = removeObsAnnoColumn(this.schema, col);
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
addObsColumn(colSchema, Ctor, value) { addObsColumn(colSchema, Ctor, value) {
/* /*
add a column to field, initializing with value. Value may add a column to field, initializing with value. Value may
@@ -105,7 +112,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
const colName = colSchema.name; const colName = colSchema.name;
if ( if (
_getColumnSchema(this.schema, "obs", colName) || _getColumnSchema(this.schema, "obs", colName) ||
this._cache.obs.hasCol(colName) (this as any)._cache.obs.hasCol(colName)
) { ) {
throw new Error("column already exists"); throw new Error("column already exists");
} }
@@ -121,7 +128,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
} else { } else {
data = new Ctor(this.nObs).fill(value); data = new Ctor(this.nObs).fill(value);
} }
newAnnoMatrix._cache.obs = this._cache.obs.withCol(colName, data); newAnnoMatrix._cache.obs = (this as any)._cache.obs.withCol(colName, data);
_normalizeCategoricalSchema( _normalizeCategoricalSchema(
colSchema, colSchema,
newAnnoMatrix._cache.obs.col(colName) newAnnoMatrix._cache.obs.col(colName)
@@ -130,15 +137,15 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'oldCol' implicitly has an 'any' type.
renameObsColumn(oldCol, newCol) { renameObsColumn(oldCol, newCol) {
/* /*
Rename the obs oldColName to newColName. oldCol must be writable. Rename the obs oldColName to newColName. oldCol must be writable.
*/ */
const oldColSchema = _getColumnSchema(this.schema, "obs", oldCol); const oldColSchema = _getColumnSchema(this.schema, "obs", oldCol);
_writableCheck(oldColSchema); // throws on error _writableCheck(oldColSchema);
const value = (this as any)._cache.obs.hasCol(oldCol)
const value = this._cache.obs.hasCol(oldCol) ? (this as any)._cache.obs.col(oldCol).asArray()
? this._cache.obs.col(oldCol).asArray()
: undefined; : undefined;
return this.dropObsColumn(oldCol).addObsColumn( return this.dropObsColumn(oldCol).addObsColumn(
{ {
@@ -150,6 +157,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
); );
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
async setObsColumnValues(col, rowLabels, value) { async setObsColumnValues(col, rowLabels, value) {
/* /*
Set all rows identified by rowLabels to value. Set all rows identified by rowLabels to value.
@@ -159,11 +167,11 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
// ensure that we have the data in cache before we manipulate it // ensure that we have the data in cache before we manipulate it
await this.fetch("obs", col); await this.fetch("obs", col);
if (!this._cache.obs.hasCol(col)) if (!(this as any)._cache.obs.hasCol(col))
throw new Error("Internal error - user annotation data missing"); throw new Error("Internal error - user annotation data missing");
const rowIndices = this.rowIndex.getOffsets(rowLabels); const rowIndices = this.rowIndex.getOffsets(rowLabels);
const data = this._cache.obs.col(col).asArray().slice(); const data = (this as any)._cache.obs.col(col).asArray().slice();
for (let i = 0, len = rowIndices.length; i < len; i += 1) { for (let i = 0, len = rowIndices.length; i < len; i += 1) {
const idx = rowIndices[i]; const idx = rowIndices[i];
if (idx === undefined) throw new Error("Unknown row label"); if (idx === undefined) throw new Error("Unknown row label");
@@ -171,7 +179,10 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
} }
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix._cache.obs = this._cache.obs.replaceColData(col, data); newAnnoMatrix._cache.obs = (this as any)._cache.obs.replaceColData(
col,
data
);
const { categories } = colSchema; const { categories } = colSchema;
if (!categories?.includes(value)) { if (!categories?.includes(value)) {
newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, value); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, value);
@@ -179,6 +190,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type.
async resetObsColumnValues(col, oldValue, newValue) { async resetObsColumnValues(col, oldValue, newValue) {
/* /*
Set all rows with value 'oldValue' to 'newValue'. Set all rows with value 'oldValue' to 'newValue'.
@@ -192,16 +204,19 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
// ensure that we have the data in cache before we manipulate it // ensure that we have the data in cache before we manipulate it
await this.fetch("obs", col); await this.fetch("obs", col);
if (!this._cache.obs.hasCol(col)) if (!(this as any)._cache.obs.hasCol(col))
throw new Error("Internal error - user annotation data missing"); throw new Error("Internal error - user annotation data missing");
const data = this._cache.obs.col(col).asArray().slice(); const data = (this as any)._cache.obs.col(col).asArray().slice();
for (let i = 0, l = data.length; i < l; i += 1) { for (let i = 0, l = data.length; i < l; i += 1) {
if (data[i] === oldValue) data[i] = newValue; if (data[i] === oldValue) data[i] = newValue;
} }
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix._cache.obs = this._cache.obs.replaceColData(col, data); newAnnoMatrix._cache.obs = (this as any)._cache.obs.replaceColData(
col,
data
);
const { categories } = colSchema; const { categories } = colSchema;
if (!categories?.includes(newValue)) { if (!categories?.includes(newValue)) {
newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, newValue); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, newValue);
@@ -209,6 +224,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
addEmbedding(colSchema) { addEmbedding(colSchema) {
/* /*
add new layout to the obs embeddings add new layout to the obs embeddings
@@ -226,6 +242,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
/** /**
** Private below ** Private below
**/ **/
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixLoader' is n... Remove this comment to see the full error message
async _doLoad(field, query) { async _doLoad(field, query) {
/* /*
_doLoad - evaluates the query against the field. Returns: _doLoad - evaluates the query against the field. Returns:
@@ -280,12 +297,14 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
Utility functions below Utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
function _writableCheck(colSchema) { function _writableCheck(colSchema) {
if (!colSchema?.writable) { if (!colSchema?.writable) {
throw new Error("Unknown or readonly obs column"); throw new Error("Unknown or readonly obs column");
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
function _writableCategoryTypeCheck(colSchema) { function _writableCategoryTypeCheck(colSchema) {
_writableCheck(colSchema); _writableCheck(colSchema);
if (colSchema.type !== "categorical") { if (colSchema.type !== "categorical") {
@@ -293,6 +312,7 @@ function _writableCategoryTypeCheck(colSchema) {
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type.
function _embLoader(baseURL, _field, query) { function _embLoader(baseURL, _field, query) {
_expectSimpleQuery(query); _expectSimpleQuery(query);
@@ -302,6 +322,7 @@ function _embLoader(baseURL, _field, query) {
return () => doBinaryRequest(url); return () => doBinaryRequest(url);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type.
function _obsOrVarLoader(baseURL, field, query) { function _obsOrVarLoader(baseURL, field, query) {
_expectSimpleQuery(query); _expectSimpleQuery(query);
@@ -311,6 +332,7 @@ function _obsOrVarLoader(baseURL, field, query) {
return () => doBinaryRequest(url); return () => doBinaryRequest(url);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type.
function _XLoader(baseURL, field, query) { function _XLoader(baseURL, field, query) {
_expectComplexQuery(query); _expectComplexQuery(query);
@@ -11,7 +11,7 @@ Undoable metareducer and the AnnoMatrix private API. It would be helpful
to make the Undoable interface better factored. to make the Undoable interface better factored.
*/ */
const annoMatrixGC = (store) => (next) => (action) => { const annoMatrixGC = (store: any) => (next: any) => (action: any) => {
if (_itIsTimeForGC()) { if (_itIsTimeForGC()) {
_doGC(store); _doGC(store);
} }
@@ -34,7 +34,7 @@ function _itIsTimeForGC() {
return false; return false;
} }
function _doGC(store) { function _doGC(store: any) {
const state = store.getState(); const state = store.getState();
// these should probably be a function imported from undoable.js, etc, as // these should probably be a function imported from undoable.js, etc, as
@@ -43,8 +43,8 @@ function _doGC(store) {
const undoableFuture = state["@@undoable/future"]; const undoableFuture = state["@@undoable/future"];
const undoableStack = undoablePast const undoableStack = undoablePast
.concat(undoableFuture) .concat(undoableFuture)
.flatMap((snapshot) => .flatMap((snapshot: any) =>
snapshot.filter((v) => v[0] === "annoMatrix").map((v) => v[1]) snapshot.filter((v: any) => v[0] === "annoMatrix").map((v: any) => v[1])
); );
const currentAnnoMatrix = state.annoMatrix; const currentAnnoMatrix = state.annoMatrix;
@@ -53,14 +53,16 @@ function _doGC(store) {
as our current gc algo is more aggressive with those not hot. as our current gc algo is more aggressive with those not hot.
*/ */
const allAnnoMatrices = new Map( const allAnnoMatrices = new Map(
undoableStack.map((m) => [m, { isHot: false }]) undoableStack.map((m: any) => [m, { isHot: false }])
); );
let am = currentAnnoMatrix; let am = currentAnnoMatrix;
while (am) { while (am) {
allAnnoMatrices.set(am, { isHot: true }); allAnnoMatrices.set(am, { isHot: true });
am = am.viewOf; am = am.viewOf;
} }
allAnnoMatrices.forEach((hints, annoMatrix) => annoMatrix._gc(hints)); allAnnoMatrices.forEach((hints, annoMatrix) =>
(annoMatrix as any)._gc(hints)
);
} }
export default annoMatrixGC; export default annoMatrixGC;
@@ -10,7 +10,7 @@ import { _dubEncURIComp } from "./fetchHelpers";
* @param {object | string} query - the query * @param {object | string} query - the query
* @returns {object | string} - the normalized query * @returns {object | string} - the normalized query
*/ */
export function _queryValidate(query) { export function _queryValidate(query: any) {
if (typeof query !== "object") return query; if (typeof query !== "object") return query;
if (query.where && query.summarize) if (query.where && query.summarize)
@@ -40,11 +40,11 @@ export function _queryValidate(query) {
throw new Error("query must specify one of where or summarize"); throw new Error("query must specify one of where or summarize");
} }
export function _expectSimpleQuery(query) { export function _expectSimpleQuery(query: any) {
if (typeof query === "object") throw new Error("expected simple query"); if (typeof query === "object") throw new Error("expected simple query");
} }
export function _expectComplexQuery(query) { export function _expectComplexQuery(query: any) {
if (typeof query !== "object") throw new Error("expected complex query"); if (typeof query !== "object") throw new Error("expected complex query");
} }
@@ -55,7 +55,7 @@ export function _expectComplexQuery(query) {
* @param {string|object} query * @param {string|object} query
* @returns the key * @returns the key
*/ */
export function _queryCacheKey(field, query) { export function _queryCacheKey(field: any, query: any) {
if (typeof query === "object") { if (typeof query === "object") {
// complex query // complex query
if (query.where) { if (query.where) {
@@ -84,22 +84,22 @@ export function _queryCacheKey(field, query) {
return `${field}/${query}`; return `${field}/${query}`;
} }
function _urlEncodeWhereQuery(q) { function _urlEncodeWhereQuery(q: any) {
const { field: queryField, column: queryColumn, value: queryValue } = q; const { field: queryField, column: queryColumn, value: queryValue } = q;
return `${_dubEncURIComp(queryField)}:${_dubEncURIComp( return `${_dubEncURIComp(queryField)}:${_dubEncURIComp(
queryColumn queryColumn
)}=${_dubEncURIComp(queryValue)}`; )}=${_dubEncURIComp(queryValue)}`;
} }
function _urlEncodeSummarizeQuery(q) { function _urlEncodeSummarizeQuery(q: any) {
const { method, field, column, values } = q; const { method, field, column, values } = q;
const filter = values const filter = values
.map((value) => _urlEncodeWhereQuery({ field, column, value })) .map((value: any) => _urlEncodeWhereQuery({ field, column, value }))
.join("&"); .join("&");
return `method=${method}&${filter}`; return `method=${method}&${filter}`;
} }
export function _urlEncodeComplexQuery(q) { export function _urlEncodeComplexQuery(q: any) {
if (typeof q === "object") { if (typeof q === "object") {
if (q.where) { if (q.where) {
return _urlEncodeWhereQuery(q.where); return _urlEncodeWhereQuery(q.where);
@@ -111,7 +111,7 @@ export function _urlEncodeComplexQuery(q) {
throw new Error("Unrecognized complex query type"); throw new Error("Unrecognized complex query type");
} }
export function _urlEncodeLabelQuery(colKey, q) { export function _urlEncodeLabelQuery(colKey: any, q: any) {
if (!colKey) throw new Error("Unsupported query by name"); if (!colKey) throw new Error("Unsupported query by name");
if (typeof q !== "string") throw new Error("Query must be a simple label."); if (typeof q !== "string") throw new Error("Query must be a simple label.");
return `${colKey}=${encodeURIComponent(q)}`; return `${colKey}=${encodeURIComponent(q)}`;
@@ -120,7 +120,7 @@ export function _urlEncodeLabelQuery(colKey, q) {
/** /**
* Generate the column key the server will send us for this query. * Generate the column key the server will send us for this query.
*/ */
export function _hashStringValues(arrayOfString) { export function _hashStringValues(arrayOfString: any) {
const hash = sha1(arrayOfString.join("")); const hash = sha1(arrayOfString.join(""));
return hash; return hash;
} }
@@ -4,7 +4,7 @@ Private helper functions related to schema
import catLabelSort from "../util/catLabelSort"; import catLabelSort from "../util/catLabelSort";
import { unassignedCategoryLabel } from "../globals"; import { unassignedCategoryLabel } from "../globals";
export function _getColumnSchema(schema, field, col) { export function _getColumnSchema(schema: any, field: any, col: any) {
/* look up the column definition */ /* look up the column definition */
switch (field) { switch (field) {
case "obs": case "obs":
@@ -26,7 +26,7 @@ export function _getColumnSchema(schema, field, col) {
} }
} }
export function _getColumnDimensionNames(schema, field, col) { export function _getColumnDimensionNames(schema: any, field: any, col: any) {
/* /*
field/col may be an alias for multiple columns. Currently used to map ND field/col may be an alias for multiple columns. Currently used to map ND
values to 1D dataframe columns for embeddings/layout. Signified by the presence values to 1D dataframe columns for embeddings/layout. Signified by the presence
@@ -39,6 +39,7 @@ export function _getColumnDimensionNames(schema, field, col) {
return colSchema.dims || [col]; return colSchema.dims || [col];
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
export function _schemaColumns(schema, field) { export function _schemaColumns(schema, field) {
switch (field) { switch (field) {
case "obs": case "obs":
@@ -52,18 +53,25 @@ export function _schemaColumns(schema, field) {
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
export function _getWritableColumns(schema, field) { export function _getWritableColumns(schema, field) {
if (field !== "obs") return []; if (field !== "obs") return [];
return schema.annotations.obs.columns return (
.filter((v) => v.writable) schema.annotations.obs.columns
.map((v) => v.name); // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'v' implicitly has an 'any' type.
.filter((v) => v.writable)
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'v' implicitly has an 'any' type.
.map((v) => v.name)
);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
export function _isContinuousType(schema) { export function _isContinuousType(schema) {
const { type } = schema; const { type } = schema;
return !(type === "string" || type === "boolean" || type === "categorical"); return !(type === "string" || type === "boolean" || type === "categorical");
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message
export function _normalizeCategoricalSchema(colSchema, col) { export function _normalizeCategoricalSchema(colSchema, col) {
const { type, writable } = colSchema; const { type, writable } = colSchema;
if ( if (
@@ -5,7 +5,7 @@ instances of AnnoMatrix, implementing common UI functions.
import { AnnoMatrixRowSubsetView, AnnoMatrixClipView } from "./views"; import { AnnoMatrixRowSubsetView, AnnoMatrixClipView } from "./views";
export function isubsetMask(annoMatrix, obsMask) { export function isubsetMask(annoMatrix: any, obsMask: any) {
/* /*
Subset annomatrix to contain the rows which have truish value in the mask. Subset annomatrix to contain the rows which have truish value in the mask.
Maks length must equal annoMatrix.nObs (row count). Maks length must equal annoMatrix.nObs (row count).
@@ -13,6 +13,7 @@ export function isubsetMask(annoMatrix, obsMask) {
return isubset(annoMatrix, _maskToList(obsMask)); return isubset(annoMatrix, _maskToList(obsMask));
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
export function isubset(annoMatrix, obsOffsets) { export function isubset(annoMatrix, obsOffsets) {
/* /*
Subset annomatrix to contain the positions contained in the obsOffsets array Subset annomatrix to contain the positions contained in the obsOffsets array
@@ -25,6 +26,7 @@ export function isubset(annoMatrix, obsOffsets) {
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
export function subset(annoMatrix, obsLabels) { export function subset(annoMatrix, obsLabels) {
/* /*
subset based on labels subset based on labels
@@ -33,6 +35,7 @@ export function subset(annoMatrix, obsLabels) {
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
export function subsetByIndex(annoMatrix, obsIndex) { export function subsetByIndex(annoMatrix, obsIndex) {
/* /*
subset based upon the new obs index. subset based upon the new obs index.
@@ -40,6 +43,7 @@ export function subsetByIndex(annoMatrix, obsIndex) {
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
export function clip(annoMatrix, qmin, qmax) { export function clip(annoMatrix, qmin, qmax) {
/* /*
Create a view that clips all continuous data to the [min, max] range. Create a view that clips all continuous data to the [min, max] range.
@@ -53,6 +57,7 @@ export function clip(annoMatrix, qmin, qmax) {
Private utility functions below Private utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'mask' implicitly has an 'any' type.
function _maskToList(mask) { function _maskToList(mask) {
/* convert masks to lists - method wastes space, but is fast */ /* convert masks to lists - method wastes space, but is fast */
if (!mask) { if (!mask) {
@@ -9,21 +9,26 @@ import { _whereCacheCreate } from "./whereCache";
import { _isContinuousType, _getColumnSchema } from "./schema"; import { _isContinuousType, _getColumnSchema } from "./schema";
class AnnoMatrixView extends AnnoMatrix { class AnnoMatrixView extends AnnoMatrix {
constructor(viewOf, rowIndex = null) { constructor(viewOf: any, rowIndex = null) {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const nObs = rowIndex ? rowIndex.size() : viewOf.nObs; const nObs = rowIndex ? rowIndex.size() : viewOf.nObs;
super(viewOf.schema, nObs, viewOf.nVar, rowIndex || viewOf.rowIndex); super(viewOf.schema, nObs, viewOf.nVar, rowIndex || viewOf.rowIndex);
this.viewOf = viewOf; this.viewOf = viewOf;
this.isView = true; this.isView = true;
} }
addObsAnnoCategory(col, category) { addObsAnnoCategory(col: any, category: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addObsAnnoCategory(col, category); newAnnoMatrix.viewOf = this.viewOf.addObsAnnoCategory(col, category);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
return newAnnoMatrix; return newAnnoMatrix;
} }
async removeObsAnnoCategory(col, category, unassignedCategory) { async removeObsAnnoCategory(
col: any,
category: any,
unassignedCategory: any
) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.removeObsAnnoCategory( newAnnoMatrix.viewOf = await this.viewOf.removeObsAnnoCategory(
col, col,
@@ -34,7 +39,7 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
dropObsColumn(col) { dropObsColumn(col: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.dropObsColumn(col); newAnnoMatrix.viewOf = this.viewOf.dropObsColumn(col);
newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col); newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col);
@@ -42,21 +47,21 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
addObsColumn(colSchema, Ctor, value) { addObsColumn(colSchema: any, Ctor: any, value: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addObsColumn(colSchema, Ctor, value); newAnnoMatrix.viewOf = this.viewOf.addObsColumn(colSchema, Ctor, value);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
return newAnnoMatrix; return newAnnoMatrix;
} }
renameObsColumn(oldCol, newCol) { renameObsColumn(oldCol: any, newCol: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.renameObsColumn(oldCol, newCol); newAnnoMatrix.viewOf = this.viewOf.renameObsColumn(oldCol, newCol);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
return newAnnoMatrix; return newAnnoMatrix;
} }
async setObsColumnValues(col, rowLabels, value) { async setObsColumnValues(col: any, rowLabels: any, value: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.setObsColumnValues( newAnnoMatrix.viewOf = await this.viewOf.setObsColumnValues(
col, col,
@@ -68,7 +73,7 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
async resetObsColumnValues(col, oldValue, newValue) { async resetObsColumnValues(col: any, oldValue: any, newValue: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.resetObsColumnValues( newAnnoMatrix.viewOf = await this.viewOf.resetObsColumnValues(
col, col,
@@ -80,7 +85,7 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
addEmbedding(colSchema) { addEmbedding(colSchema: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addEmbedding(colSchema); newAnnoMatrix.viewOf = this.viewOf.addEmbedding(colSchema);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
@@ -92,17 +97,20 @@ class AnnoMatrixMapView extends AnnoMatrixView {
/* /*
A view which knows how to transform its data. A view which knows how to transform its data.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type.
constructor(viewOf, mapFn) { constructor(viewOf, mapFn) {
super(viewOf); super(viewOf);
this.mapFn = mapFn; (this as any).mapFn = mapFn;
} }
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixMapView' is ... Remove this comment to see the full error message
async _doLoad(field, query) { async _doLoad(field, query) {
const df = await this.viewOf._fetch(field, query); const df = await this.viewOf._fetch(field, query);
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colData' implicitly has an 'any' type.
const dfMapped = df.mapColumns((colData, colIdx) => { const dfMapped = df.mapColumns((colData, colIdx) => {
const colLabel = df.colIndex.getLabel(colIdx); const colLabel = df.colIndex.getLabel(colIdx);
const colSchema = _getColumnSchema(this.schema, field, colLabel); const colSchema = _getColumnSchema(this.schema, field, colLabel);
return this.mapFn(field, colLabel, colSchema, colData, df); return (this as any).mapFn(field, colLabel, colSchema, colData, df);
}); });
const whereCacheUpdate = _whereCacheCreate( const whereCacheUpdate = _whereCacheCreate(
field, field,
@@ -117,12 +125,14 @@ export class AnnoMatrixClipView extends AnnoMatrixMapView {
/* /*
A view which is a clipped transformation of its parent A view which is a clipped transformation of its parent
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type.
constructor(viewOf, qmin, qmax) { constructor(viewOf, qmin, qmax) {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
super(viewOf, (field, colLabel, colSchema, colData, df) => super(viewOf, (field, colLabel, colSchema, colData, df) =>
_clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax)
); );
this.isClipped = true; (this as any).isClipped = true;
this.clipRange = [qmin, qmax]; (this as any).clipRange = [qmin, qmax];
Object.seal(this); Object.seal(this);
} }
} }
@@ -131,11 +141,13 @@ export class AnnoMatrixRowSubsetView extends AnnoMatrixView {
/* /*
A view which is a subset of total rows. A view which is a subset of total rows.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type.
constructor(viewOf, rowIndex) { constructor(viewOf, rowIndex) {
super(viewOf, rowIndex); super(viewOf, rowIndex);
Object.seal(this); Object.seal(this);
} }
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixRowSubsetVie... Remove this comment to see the full error message
async _doLoad(field, query) { async _doLoad(field, query) {
const df = await this.viewOf._fetch(field, query); const df = await this.viewOf._fetch(field, query);
@@ -158,6 +170,7 @@ export class AnnoMatrixRowSubsetView extends AnnoMatrixView {
Utility functions below Utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
function _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) { function _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) {
/* only clip obs and var scalar columns */ /* only clip obs and var scalar columns */
if (field !== "obs" && field !== "X") return colData; if (field !== "obs" && field !== "X") return colData;
@@ -51,7 +51,12 @@ creates a cache entry of:
import { _getColumnDimensionNames } from "./schema"; import { _getColumnDimensionNames } from "./schema";
import { _hashStringValues } from "./query"; import { _hashStringValues } from "./query";
export function _whereCacheGet(whereCache, schema, field, query) { export function _whereCacheGet(
whereCache: any,
schema: any,
field: any,
query: any
) {
/* /*
query will either be an where query (object) or a column name (string). query will either be an where query (object) or a column name (string).
@@ -85,6 +90,7 @@ export function _whereCacheGet(whereCache, schema, field, query) {
return _getColumnDimensionNames(schema, field, query) ?? [undefined]; return _getColumnDimensionNames(schema, field, query) ?? [undefined];
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
export function _whereCacheCreate(field, query, columnLabels) { export function _whereCacheCreate(field, query, columnLabels) {
/* /*
Create a new whereCache Create a new whereCache
@@ -131,10 +137,11 @@ export function _whereCacheCreate(field, query, columnLabels) {
return {}; return {};
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'dst' implicitly has an 'any' type.
function __mergeQueries(dst, src) { function __mergeQueries(dst, src) {
for (const [queryField, columnMap] of Object.entries(src)) { for (const [queryField, columnMap] of Object.entries(src)) {
dst[queryField] = dst[queryField] || new Map(); dst[queryField] = dst[queryField] || new Map();
for (const [queryColumn, valueMap] of columnMap) { for (const [queryColumn, valueMap] of columnMap as any) {
if (!dst[queryField].has(queryColumn)) if (!dst[queryField].has(queryColumn))
dst[queryField].set(queryColumn, new Map()); dst[queryField].set(queryColumn, new Map());
for (const [queryValue, columnLabels] of valueMap) { for (const [queryValue, columnLabels] of valueMap) {
@@ -144,6 +151,7 @@ function __mergeQueries(dst, src) {
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'dst' implicitly has an 'any' type.
function __whereCacheMerge(dst, src) { function __whereCacheMerge(dst, src) {
/* /*
merge src into dst (modifies dst) merge src into dst (modifies dst)
@@ -161,6 +169,7 @@ function __whereCacheMerge(dst, src) {
dst.summarize = dst.summarize || {}; dst.summarize = dst.summarize || {};
for (const [field, method] of Object.entries(src.summarize)) { for (const [field, method] of Object.entries(src.summarize)) {
dst.summarize[field] = dst.summarize[field] || {}; dst.summarize[field] = dst.summarize[field] || {};
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
for (const [methodName, query] of Object.entries(method)) { for (const [methodName, query] of Object.entries(method)) {
dst.summarize[field][methodName] = dst.summarize[field][methodName] =
dst.summarize[field][methodName] || {}; dst.summarize[field][methodName] || {};
@@ -171,6 +180,7 @@ function __whereCacheMerge(dst, src) {
return dst; return dst;
} }
// @ts-expect-error ts-migrate(7019) FIXME: Rest parameter 'caches' implicitly has an 'any[]' ... Remove this comment to see the full error message
export function _whereCacheMerge(...caches) { export function _whereCacheMerge(...caches) {
return caches.reduce(__whereCacheMerge, {}); return caches.reduce(__whereCacheMerge, {});
} }
@@ -1,30 +1,49 @@
import React from "react"; import React from "react";
import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core"; import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core";
class AnnoDialog extends React.PureComponent { type State = any;
constructor(props) {
class AnnoDialog extends React.PureComponent<{}, State> {
constructor(props: {}) {
super(props); super(props);
this.state = {}; this.state = {};
} }
render() { render() {
const { 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, 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, 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, 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, instruction,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cancelTooltipContent' does not exist on ... Remove this comment to see the full error message
cancelTooltipContent, 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, 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, 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, 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, annoInput,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryInstructions' does not exist on... Remove this comment to see the full error message
secondaryInstructions, 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, 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, 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, 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, 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, secondaryButtonText,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSecondaryButtonSubmit' does not ex... Remove this comment to see the full error message
handleSecondaryButtonSubmit, 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, primaryButtonProps,
} = this.props; } = this.props;
@@ -15,30 +15,32 @@ import TermsOfServicePrompt from "./termsPrompt";
import actions from "../actions"; 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) => ({ @connect((state) => ({
loading: state.controls.loading, loading: (state as any).controls.loading,
error: state.controls.error, error: (state as any).controls.error,
graphRenderCounter: state.controls.graphRenderCounter, graphRenderCounter: (state as any).controls.graphRenderCounter,
})) }))
class App extends React.Component { class App extends React.Component {
componentDidMount() { 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; const { dispatch } = this.props;
/* listen for url changes, fire one when we start the app up */ /* listen for url changes, fire one when we start the app up */
window.addEventListener("popstate", this._onURLChanged); window.addEventListener("popstate", this._onURLChanged);
this._onURLChanged(); this._onURLChanged();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
dispatch(actions.doInitialDataLoad(window.location.search)); dispatch(actions.doInitialDataLoad(window.location.search));
this.forceUpdate(); this.forceUpdate();
} }
_onURLChanged() { _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; const { dispatch } = this.props;
dispatch({ type: "url changed", url: document.location.href }); dispatch({ type: "url changed", url: document.location.href });
} }
render() { 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; const { loading, error, graphRenderCounter } = this.props;
return ( return (
<Container> <Container>
@@ -70,13 +72,15 @@ class App extends React.Component {
{loading || error ? null : ( {loading || error ? null : (
<Layout> <Layout>
<LeftSideBar /> <LeftSideBar />
{(viewportRef) => ( {(viewportRef: any) => (
<> <>
<MenuBar /> <MenuBar />
<Embedding /> <Embedding />
<Autosave /> <Autosave />
<TermsOfServicePrompt /> <TermsOfServicePrompt />
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
<Legend viewportRef={viewportRef} /> <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} /> <Graph key={graphRenderCounter} viewportRef={viewportRef} />
</> </>
)} )}
@@ -11,18 +11,23 @@ import {
Tooltip, Tooltip,
} from "@blueprintjs/core"; } from "@blueprintjs/core";
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) => ({ @connect((state) => ({
idhash: state.config?.parameters?.["annotations-user-data-idhash"] ?? null, idhash:
annotations: state.annotations, (state as any).config?.parameters?.["annotations-user-data-idhash"] ?? null,
auth: state.config?.authentication, annotations: (state as any).annotations,
userInfo: state.userInfo, auth: (state as any).config?.authentication,
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, userInfo: (state as any).userInfo,
writableCategoriesEnabled:
(state as any).config?.parameters?.annotations ?? false,
writableGenesetsEnabled: !( writableGenesetsEnabled: !(
state.config?.parameters?.annotations_genesets_readonly ?? true (state as any).config?.parameters?.annotations_genesets_readonly ?? true
), ),
})) }))
class FilenameDialog extends React.Component { class FilenameDialog extends React.Component<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
filenameText: "", filenameText: "",
@@ -32,9 +37,9 @@ class FilenameDialog extends React.Component {
dismissFilenameDialog = () => {}; dismissFilenameDialog = () => {};
handleCreateFilename = () => { 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 { dispatch } = this.props;
const { filenameText } = this.state; const { filenameText } = this.state;
dispatch({ dispatch({
type: "set annotations collection name", type: "set annotations collection name",
data: filenameText, data: filenameText,
@@ -45,26 +50,26 @@ class FilenameDialog extends React.Component {
const legalNames = /^\w+$/; const legalNames = /^\w+$/;
const { filenameText } = this.state; const { filenameText } = this.state;
let err = false; let err = false;
if (filenameText === "") { if (filenameText === "") {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'boolean'.
err = "empty_string"; err = "empty_string";
} else if (!legalNames.test(filenameText)) { } else if (!legalNames.test(filenameText)) {
/* /*
IMPORTANT: this test must ultimately match the test applied by the IMPORTANT: this test must ultimately match the test applied by the
backend, which is designed to ensure a safe file name can be created 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 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. 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'.
err = "characters"; err = "characters";
} }
return err; return err;
}; };
filenameErrorMessage = () => { filenameErrorMessage = () => {
const err = this.filenameError(); const err = this.filenameError();
let markup = null; 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") { if (err === "empty_string") {
markup = ( markup = (
<span <span
@@ -78,6 +83,7 @@ class FilenameDialog extends React.Component {
Name cannot be blank Name cannot be blank
</span> </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") { } else if (err === "characters") {
markup = ( markup = (
<span <span
@@ -97,14 +103,18 @@ class FilenameDialog extends React.Component {
render() { render() {
const { const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
writableCategoriesEnabled, writableCategoriesEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableGenesetsEnabled' does not exist ... Remove this comment to see the full error message
writableGenesetsEnabled, 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, 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, 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, userInfo,
} = this.props; } = this.props;
const { filenameText } = this.state; const { filenameText } = this.state;
return (writableCategoriesEnabled || writableGenesetsEnabled) && return (writableCategoriesEnabled || writableGenesetsEnabled) &&
annotations.promptForFilename && annotations.promptForFilename &&
!annotations.dataCollectionNameIsReadOnly && !annotations.dataCollectionNameIsReadOnly &&
@@ -128,6 +138,7 @@ class FilenameDialog extends React.Component {
<InputGroup <InputGroup
autoFocus autoFocus
value={filenameText} value={filenameText}
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
intent={this.filenameError(filenameText) ? "warning" : "none"} intent={this.filenameError(filenameText) ? "warning" : "none"}
onChange={(e) => onChange={(e) =>
this.setState({ filenameText: e.target.value }) this.setState({ filenameText: e.target.value })
@@ -138,12 +149,14 @@ class FilenameDialog extends React.Component {
<p <p
style={{ style={{
marginTop: 7, marginTop: 7,
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
visibility: this.filenameError(filenameText) visibility: this.filenameError(filenameText)
? "visible" ? "visible"
: "hidden", : "hidden",
color: Colors.ORANGE3, color: Colors.ORANGE3,
}} }}
> >
{/* @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. */}
{this.filenameErrorMessage(filenameText)} {this.filenameErrorMessage(filenameText)}
</p> </p>
</div> </div>
@@ -171,6 +184,7 @@ class FilenameDialog extends React.Component {
<Button onClick={this.dismissFilenameDialog}>Cancel</Button> <Button onClick={this.dismissFilenameDialog}>Cancel</Button>
</Tooltip> </Tooltip>
<Button <Button
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
disabled={!filenameText || this.filenameError(filenameText)} disabled={!filenameText || this.filenameError(filenameText)}
onClick={this.handleCreateFilename} onClick={this.handleCreateFilename}
intent="primary" intent="primary"
@@ -3,23 +3,30 @@ import { connect } from "react-redux";
import actions from "../../actions"; import actions from "../../actions";
import FilenameDialog from "./filenameDialog"; import FilenameDialog from "./filenameDialog";
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) => ({ @connect((state) => ({
annotations: state.annotations, annotations: (state as any).annotations,
obsAnnotationSaveInProgress: obsAnnotationSaveInProgress:
state.autosave?.obsAnnotationSaveInProgress ?? false, (state as any).autosave?.obsAnnotationSaveInProgress ?? false,
genesetSaveInProgress: state.autosave?.genesetSaveInProgress ?? false, genesetSaveInProgress:
error: state.autosave?.error, (state as any).autosave?.genesetSaveInProgress ?? false,
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, error: (state as any).autosave?.error,
writableCategoriesEnabled:
(state as any).config?.parameters?.annotations ?? false,
writableGenesetsEnabled: !( writableGenesetsEnabled: !(
state.config?.parameters?.annotations_genesets_readonly ?? true (state as any).config?.parameters?.annotations_genesets_readonly ?? true
), ),
annoMatrix: state.annoMatrix, annoMatrix: (state as any).annoMatrix,
genesets: state.genesets, genesets: (state as any).genesets,
lastSavedAnnoMatrix: state.autosave?.lastSavedAnnoMatrix, lastSavedAnnoMatrix: (state as any).autosave?.lastSavedAnnoMatrix,
lastSavedGenesets: state.autosave?.lastSavedGenesets, lastSavedGenesets: (state as any).autosave?.lastSavedGenesets,
})) }))
class Autosave extends React.Component { class Autosave extends React.Component<{}, State> {
constructor(props) { clearInterval: any;
constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
timer: null, timer: null,
@@ -27,8 +34,8 @@ class Autosave extends React.Component {
} }
componentDidMount() { 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; const { writableCategoriesEnabled, writableGenesetsEnabled } = this.props;
let { timer } = this.state; let { timer } = this.state;
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
if (writableCategoriesEnabled || writableGenesetsEnabled) { if (writableCategoriesEnabled || writableGenesetsEnabled) {
@@ -46,8 +53,11 @@ class Autosave extends React.Component {
tick = () => { tick = () => {
const { 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, dispatch,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsAnnotationSaveInProgress' does not ex... Remove this comment to see the full error message
obsAnnotationSaveInProgress, obsAnnotationSaveInProgress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetSaveInProgress' does not exist on... Remove this comment to see the full error message
genesetSaveInProgress, genesetSaveInProgress,
} = this.props; } = this.props;
if (!obsAnnotationSaveInProgress && this.needToSaveObsAnnotations()) { if (!obsAnnotationSaveInProgress && this.needToSaveObsAnnotations()) {
@@ -60,12 +70,14 @@ class Autosave extends React.Component {
needToSaveObsAnnotations = () => { needToSaveObsAnnotations = () => {
/* return true if we need to save obs cell labels, false if we don't */ /* 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; const { annoMatrix, lastSavedAnnoMatrix } = this.props;
return actions.needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix); return actions.needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix);
}; };
needToSaveGenesets = () => { needToSaveGenesets = () => {
/* return true if we need to save gene ses, false if we do not */ /* 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; const { genesets, lastSavedGenesets } = this.props;
return genesets.initialized && genesets.genesets !== lastSavedGenesets; return genesets.initialized && genesets.genesets !== lastSavedGenesets;
}; };
@@ -75,11 +87,13 @@ class Autosave extends React.Component {
} }
saveInProgress() { 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; const { obsAnnotationSaveInProgress, genesetSaveInProgress } = this.props;
return obsAnnotationSaveInProgress || genesetSaveInProgress; return obsAnnotationSaveInProgress || genesetSaveInProgress;
} }
statusMessage() { 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; const { error } = this.props;
if (error) { if (error) {
return `Autosave error: ${error}`; return `Autosave error: ${error}`;
@@ -89,14 +103,15 @@ class Autosave extends React.Component {
render() { render() {
const { const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
writableCategoriesEnabled, writableCategoriesEnabled,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'writableGenesetsEnabled' does not exist ... Remove this comment to see the full error message
writableGenesetsEnabled, 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, lastSavedAnnoMatrix,
} = this.props; } = this.props;
const initialDataLoadComplete = lastSavedAnnoMatrix; const initialDataLoadComplete = lastSavedAnnoMatrix;
if (!writableCategoriesEnabled && !writableGenesetsEnabled) return null; if (!writableCategoriesEnabled && !writableGenesetsEnabled) return null;
return ( return (
<div <div
id="autosave" id="autosave"
@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import * as globals from "../../globals"; import * as globals from "../../globals";
const ErrorLoading = ({ displayName, zebra }) => { const ErrorLoading = ({ displayName, zebra }: any) => {
return ( return (
<div <div
style={{ style={{
@@ -2,13 +2,21 @@ import React from "react";
const HistogramFooter = React.memo( 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, 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, 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, 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, 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, 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, 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, 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, isGeneSetSummary,
}) => { }) => {
/* /*
@@ -5,14 +5,23 @@ import * as globals from "../../globals";
const HistogramHeader = React.memo( 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, 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, 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, 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, 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, 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, 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, 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, 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, isObs,
}) => { }) => {
/* /*
@@ -18,7 +18,7 @@ const Histogram = ({
isColorBy, isColorBy,
selectionRange, selectionRange,
mini, mini,
}) => { }: any) => {
const svgRef = useRef(null); const svgRef = useRef(null);
const [brush, setBrush] = useState(null); const [brush, setBrush] = useState(null);
@@ -69,14 +69,18 @@ const Histogram = ({
.data(bins) .data(bins)
.enter() .enter()
.append("rect") .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("x", (d, i) => x(binStart(i)) + 1)
.attr("y", (d) => y(d)) .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("width", (d, i) => x(binEnd(i)) - x(binStart(i)) - binPadding)
.attr("height", (d) => y(0) - y(d)) .attr("height", (d) => y(0) - y(d))
.style( .style(
"fill", "fill",
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
isColorBy isColorBy
? (d, i) => colorScale(histogramScale(binStart(i))) ? // @ts-expect-error ts-migrate(6133) FIXME: 'd' is declared but its value is never read.
(d: any, i: any) => colorScale(histogramScale(binStart(i)))
: defaultBarColor : defaultBarColor
); );
} }
@@ -101,6 +105,7 @@ const Histogram = ({
const brushXselection = container const brushXselection = container
.insert("g") .insert("g")
.attr("class", "brush") .attr("class", "brush")
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
.attr("data-testid", `${svgRef.current.dataset.testid}-brushable-area`) .attr("data-testid", `${svgRef.current.dataset.testid}-brushable-area`)
.call(brushX); .call(brushX);
@@ -113,6 +118,7 @@ const Histogram = ({
d3 d3
.axisBottom(x) .axisBottom(x)
.ticks(4) .ticks(4)
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
.tickFormat(d3.format(maybeScientific(x))) .tickFormat(d3.format(maybeScientific(x)))
); );
@@ -126,8 +132,9 @@ const Histogram = ({
.axisRight(y) .axisRight(y)
.ticks(3) .ticks(3)
.tickFormat( .tickFormat(
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
d3.format( d3.format(
y.domain().some((n) => Math.abs(n) >= 10000) ? ".0e" : "," y.domain().some((n: any) => Math.abs(n) >= 10000) ? ".0e" : ","
) )
) )
); );
@@ -137,6 +144,7 @@ const Histogram = ({
svg.selectAll(".axis path").style("stroke", "rgb(230,230,230)"); svg.selectAll(".axis path").style("stroke", "rgb(230,230,230)");
svg.selectAll(".axis line").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 }); setBrush({ brushX, brushXselection });
} }
}, [histogram, isColorBy]); }, [histogram, isColorBy]);
@@ -146,6 +154,7 @@ const Histogram = ({
paint/update selection brush paint/update selection brush
*/ */
if (!brush) return; if (!brush) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'brushX' does not exist on type 'null'.
const { brushX, brushXselection } = brush; const { brushX, brushXselection } = brush;
const selection = d3.brushSelection(brushXselection.node()); const selection = d3.brushSelection(brushXselection.node());
if (!selectionRange && selection) { if (!selectionRange && selection) {
@@ -162,7 +171,9 @@ const Histogram = ({
} else { } else {
/* there is an active selection and a brush - make sure they match */ /* there is an active selection and a brush - make sure they match */
const moveDeltaThreshold = 1; 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]); 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]); const dX1 = Math.abs(x1 - selection[1]);
/* /*
only update the brush if it is grossly incorrect, only update the brush if it is grossly incorrect,
@@ -29,27 +29,31 @@ const MARGIN_MINI = {
const WIDTH_MINI = 120 - MARGIN_MINI.LEFT - MARGIN_MINI.RIGHT; const WIDTH_MINI = 120 - MARGIN_MINI.LEFT - MARGIN_MINI.RIGHT;
const HEIGHT_MINI = 15 - MARGIN_MINI.TOP - MARGIN_MINI.BOTTOM; 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) => { @connect((state, ownProps) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isObs' does not exist on type '{}'.
const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps; const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
const myName = makeContinuousDimensionName( const myName = makeContinuousDimensionName(
{ isObs, isUserDefined, isGeneSetSummary }, { isObs, isUserDefined, isGeneSetSummary },
field field
); );
return { return {
annoMatrix: state.annoMatrix, annoMatrix: (state as any).annoMatrix,
isScatterplotXXaccessor: state.controls.scatterplotXXaccessor === field, isScatterplotXXaccessor:
isScatterplotYYaccessor: state.controls.scatterplotYYaccessor === field, (state as any).controls.scatterplotXXaccessor === field,
continuousSelectionRange: state.continuousSelection[myName], isScatterplotYYaccessor:
isColorAccessor: state.colors.colorAccessor === field, (state as any).controls.scatterplotYYaccessor === field,
continuousSelectionRange: (state as any).continuousSelection[myName],
isColorAccessor: (state as any).colors.colorAccessor === field,
}; };
}) })
class HistogramBrush extends React.PureComponent { class HistogramBrush extends React.PureComponent {
static watchAsync(props, prevProps) { static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps); return !shallowEqual(props.watchProps, prevProps.watchProps);
} }
/* memoized closure to prevent HistogramHeader unecessary repaint */ /* memoized closure to prevent HistogramHeader unecessary repaint */
handleColorAction = memoize((dispatch) => (field, isObs) => { handleColorAction = memoize((dispatch) => (field: any, isObs: any) => {
if (isObs) { if (isObs) {
dispatch({ dispatch({
type: "color by continuous metadata", type: "color by continuous metadata",
@@ -60,25 +64,31 @@ class HistogramBrush extends React.PureComponent {
} }
}); });
onBrush = (selection, x, eventType) => { // @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
onBrush = (selection: any, x: any, eventType: any) => {
const type = `continuous metadata histogram ${eventType}`; const type = `continuous metadata histogram ${eventType}`;
return () => { return () => {
const { 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, 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, 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, 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, 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, isGeneSetSummary,
} = this.props; } = this.props;
// ignore programmatically generated events // ignore programmatically generated events
if (!d3.event.sourceEvent) return; if (!(d3 as any).event.sourceEvent) return;
// ignore cascading events, which are programmatically generated // ignore cascading events, which are programmatically generated
if (d3.event.sourceEvent.sourceEvent) return; if ((d3 as any).event.sourceEvent.sourceEvent) return;
const query = this.createQuery(); const query = this.createQuery();
const range = d3.event.selection const range = (d3 as any).event.selection
? [x(d3.event.selection[0]), x(d3.event.selection[1])] ? [x((d3 as any).event.selection[0]), x((d3 as any).event.selection[1])]
: null; : null;
const otherProps = { const otherProps = {
selection: field, selection: field,
@@ -94,42 +104,52 @@ class HistogramBrush extends React.PureComponent {
}; };
}; };
onBrushEnd = (selection, x) => { // @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
onBrushEnd = (selection: any, x: any) => {
return () => { return () => {
const { 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, 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, 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, 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, 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, isGeneSetSummary,
} = this.props; } = this.props;
const minAllowedBrushSize = 10; const minAllowedBrushSize = 10;
const smallAmountToAvoidInfiniteLoop = 0.1; const smallAmountToAvoidInfiniteLoop = 0.1;
// ignore programmatically generated events // ignore programmatically generated events
if (!d3.event.sourceEvent) return; if (!(d3 as any).event.sourceEvent) return;
// ignore cascading events, which are programmatically generated // ignore cascading events, which are programmatically generated
if (d3.event.sourceEvent.sourceEvent) return; if ((d3 as any).event.sourceEvent.sourceEvent) return;
let type; let type;
let range = null; let range = null;
if (d3.event.selection) { if ((d3 as any).event.selection) {
type = "continuous metadata histogram end"; type = "continuous metadata histogram end";
if ( if (
d3.event.selection[1] - d3.event.selection[0] > (d3 as any).event.selection[1] - (d3 as any).event.selection[0] >
minAllowedBrushSize minAllowedBrushSize
) { ) {
range = [x(d3.event.selection[0]), x(d3.event.selection[1])]; range = [
x((d3 as any).event.selection[0]),
x((d3 as any).event.selection[1]),
];
} else { } else {
/* the user selected range is too small and will be hidden #587, so take control of it procedurally */ /* 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 */ /* https://stackoverflow.com/questions/12354729/d3-js-limit-size-of-brush */
const procedurallyResizedBrushWidth = const procedurallyResizedBrushWidth =
d3.event.selection[0] + (d3 as any).event.selection[0] +
minAllowedBrushSize + minAllowedBrushSize +
smallAmountToAvoidInfiniteLoop; // smallAmountToAvoidInfiniteLoop; //
range = [
range = [x(d3.event.selection[0]), x(procedurallyResizedBrushWidth)]; x((d3 as any).event.selection[0]),
x(procedurallyResizedBrushWidth),
];
} }
} else { } else {
type = "continuous metadata histogram cancel"; type = "continuous metadata histogram cancel";
@@ -151,6 +171,7 @@ class HistogramBrush extends React.PureComponent {
}; };
handleSetGeneAsScatterplotX = () => { 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; const { dispatch, field } = this.props;
dispatch({ dispatch({
type: "set scatterplot x", type: "set scatterplot x",
@@ -159,6 +180,7 @@ class HistogramBrush extends React.PureComponent {
}; };
handleSetGeneAsScatterplotY = () => { 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; const { dispatch, field } = this.props;
dispatch({ dispatch({
type: "set scatterplot y", type: "set scatterplot y",
@@ -168,10 +190,15 @@ class HistogramBrush extends React.PureComponent {
removeHistogram = () => { removeHistogram = () => {
const { 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, 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, 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, isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor, isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor, isScatterplotYYaccessor,
} = this.props; } = this.props;
dispatch({ dispatch({
@@ -198,11 +225,13 @@ class HistogramBrush extends React.PureComponent {
}; };
fetchAsyncProps = async () => { 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 { annoMatrix, width } = this.props;
const { isClipped } = annoMatrix; const { isClipped } = annoMatrix;
const query = this.createQuery(); 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 = await annoMatrix.fetch(...query); const df = await annoMatrix.fetch(...query);
const column = df.icol(0); const column = df.icol(0);
@@ -261,7 +290,7 @@ class HistogramBrush extends React.PureComponent {
}; };
// eslint-disable-next-line class-methods-use-this -- instance method allows for memoization per annotation // eslint-disable-next-line class-methods-use-this -- instance method allows for memoization per annotation
calcHistogramCache(col, newMargin, newWidth, newHeight) { calcHistogramCache(col: any, newMargin: any, newWidth: any, newHeight: any) {
/* /*
recalculate expensive stuff, notably bins, summaries, etc. recalculate expensive stuff, notably bins, summaries, etc.
*/ */
@@ -269,35 +298,30 @@ class HistogramBrush extends React.PureComponent {
const summary = col.summarize(); /* this is memoized, so it's free the second time you call it */ const summary = col.summarize(); /* this is memoized, so it's free the second time you call it */
const { min: domainMin, max: domainMax } = summary; const { min: domainMin, max: domainMax } = summary;
const numBins = 40; const numBins = 40;
const { const { TOP: topMargin, LEFT: leftMargin } = newMargin;
TOP: topMargin, (histogramCache as any).domain = [domainMin, domainMax];
LEFT: leftMargin, /* doesn't change with mini */ (histogramCache as any).x = d3
} = newMargin; /* changes with mini */
histogramCache.domain = [
domainMin,
domainMax,
]; /* doesn't change with mini */
histogramCache.x = d3
.scaleLinear() .scaleLinear()
.domain([domainMin, domainMax]) .domain([domainMin, domainMax])
.range([leftMargin, leftMargin + newWidth]); .range([leftMargin, leftMargin + newWidth]);
histogramCache.bins = col.histogram(numBins, [ (histogramCache as any).bins = col.histogram(numBins, [
domainMin, domainMin,
domainMax, domainMax,
]); /* memoized */ ]);
/* memoized */ (histogramCache as any).binWidth =
(domainMax - domainMin) / numBins;
histogramCache.binWidth = (domainMax - domainMin) / numBins; (histogramCache as any).binStart = (i: any) =>
domainMin + i * (histogramCache as any).binWidth;
(histogramCache as any).binEnd = (i: any) =>
domainMin + (i + 1) * (histogramCache as any).binWidth;
histogramCache.binStart = (i) => domainMin + i * histogramCache.binWidth; const yMax = (histogramCache as any).bins.reduce((l: any, r: any) =>
histogramCache.binEnd = (i) => l > r ? l : r
domainMin + (i + 1) * histogramCache.binWidth; );
const yMax = histogramCache.bins.reduce((l, r) => (l > r ? l : r)); (histogramCache as any).y = d3
histogramCache.y = d3
.scaleLinear() .scaleLinear()
.domain([0, yMax]) .domain([0, yMax])
.range([topMargin + newHeight, topMargin]); .range([topMargin + newHeight, topMargin]);
@@ -306,13 +330,8 @@ class HistogramBrush extends React.PureComponent {
} }
createQuery() { createQuery() {
const { // @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, const { isObs, isGeneSetSummary, field, setGenes, annoMatrix } = this.props;
isGeneSetSummary,
field,
setGenes,
annoMatrix,
} = this.props;
const { schema } = annoMatrix; const { schema } = annoMatrix;
if (isObs) { if (isObs) {
return ["obs", field]; return ["obs", field];
@@ -349,21 +368,35 @@ class HistogramBrush extends React.PureComponent {
render() { render() {
const { 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, 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, 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, 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, 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, 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, isGeneSetSummary,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor, isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor, 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, zebra,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'continuousSelectionRange' does not exist... Remove this comment to see the full error message
continuousSelectionRange, 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, 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, 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, setGenes,
} = this.props; } = 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; let { width } = this.props;
if (!width) { if (!width) {
width = mini ? WIDTH_MINI : WIDTH; width = mini ? WIDTH_MINI : WIDTH;
@@ -392,7 +425,7 @@ class HistogramBrush extends React.PureComponent {
</Async.Rejected> </Async.Rejected>
<Async.Fulfilled> <Async.Fulfilled>
{(asyncProps) => {(asyncProps) =>
asyncProps.OK2Render ? ( (asyncProps as any).OK2Render ? (
<div <div
id={`histogram_${fieldForId}`} id={`histogram_${fieldForId}`}
data-testid={`histogram-${field}`} data-testid={`histogram-${field}`}
@@ -404,6 +437,7 @@ class HistogramBrush extends React.PureComponent {
> >
{!mini && isObs ? ( {!mini && isObs ? (
<HistogramHeader <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} fieldId={field}
isColorBy={isColorAccessor} isColorBy={isColorAccessor}
isObs={isObs} isObs={isObs}
@@ -422,9 +456,11 @@ class HistogramBrush extends React.PureComponent {
<Histogram <Histogram
field={field} field={field}
fieldForId={fieldForId} fieldForId={fieldForId}
display={asyncProps.isSingleValue ? "none" : "block"} display={(asyncProps as any).isSingleValue ? "none" : "block"}
histogram={ histogram={
mini ? asyncProps.miniHistogram : asyncProps.histogram mini
? (asyncProps as any).miniHistogram
: (asyncProps as any).histogram
} }
width={width} width={width}
height={mini ? HEIGHT_MINI : HEIGHT} height={mini ? HEIGHT_MINI : HEIGHT}
@@ -437,14 +473,15 @@ class HistogramBrush extends React.PureComponent {
/> />
{!mini && ( {!mini && (
<HistogramFooter <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} isGeneSetSummary={isGeneSetSummary}
isObs={isObs} isObs={isObs}
displayName={field} displayName={field}
hideRanges={asyncProps.isSingleValue} hideRanges={(asyncProps as any).isSingleValue}
rangeMin={asyncProps.unclippedRange[0]} rangeMin={(asyncProps as any).unclippedRange[0]}
rangeMax={asyncProps.unclippedRange[1]} rangeMax={(asyncProps as any).unclippedRange[1]}
rangeColorMin={asyncProps.unclippedRangeColor[0]} rangeColorMin={(asyncProps as any).unclippedRangeColor[0]}
rangeColorMax={asyncProps.unclippedRangeColor[1]} rangeColorMax={(asyncProps as any).unclippedRangeColor[1]}
/> />
)} )}
</div> </div>
@@ -3,7 +3,7 @@ import { Button } from "@blueprintjs/core";
import * as globals from "../../globals"; import * as globals from "../../globals";
const StillLoading = ({ zebra, displayName }) => { const StillLoading = ({ zebra, displayName }: any) => {
/* /*
Render a loading indicator for the field. Render a loading indicator for the field.
*/ */
@@ -2,16 +2,21 @@ import React from "react";
import { Button, MenuItem } from "@blueprintjs/core"; import { Button, MenuItem } from "@blueprintjs/core";
import { Select } from "@blueprintjs/select"; import { Select } from "@blueprintjs/select";
class DuplicateCategorySelect extends React.PureComponent { type State = any;
constructor(props) {
class DuplicateCategorySelect extends React.PureComponent<{}, State> {
constructor(props: {}) {
super(props); super(props);
this.state = {}; this.state = {};
} }
render() { render() {
const { 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, 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, categoryToDuplicate,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleModalDuplicateCategorySelection' d... Remove this comment to see the full error message
handleModalDuplicateCategorySelection, handleModalDuplicateCategorySelection,
} = this.props; } = this.props;
return ( return (
@@ -31,7 +36,9 @@ class DuplicateCategorySelect extends React.PureComponent {
<MenuItem <MenuItem
data-testclass="duplicate-category-dropdown-option" data-testclass="duplicate-category-dropdown-option"
onClick={handleClick} 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} 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} text={d}
/> />
); );
@@ -5,20 +5,24 @@ import LabelInput from "../../labelInput";
import { labelPrompt, isLabelErroneous } from "../labelUtil"; import { labelPrompt, isLabelErroneous } from "../labelUtil";
import actions from "../../../actions"; import actions from "../../../actions";
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) => ({ @connect((state) => ({
annotations: state.annotations, annotations: (state as any).annotations,
schema: state.annoMatrix?.schema, schema: (state as any).annoMatrix?.schema,
obsCrossfilter: state.obsCrossfilter, obsCrossfilter: (state as any).obsCrossfilter,
})) }))
class Category extends React.PureComponent { class Category extends React.PureComponent<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
newLabelText: "", newLabelText: "",
}; };
} }
disableAddNewLabelMode = (e) => { 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; const { dispatch } = this.props;
this.setState({ this.setState({
newLabelText: "", newLabelText: "",
@@ -29,10 +33,11 @@ class Category extends React.PureComponent {
if (e) e.preventDefault(); if (e) e.preventDefault();
}; };
handleAddNewLabelToCategory = (e) => { 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 { dispatch, metadataField } = this.props;
const { newLabelText } = this.state; const { newLabelText } = this.state;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
this.disableAddNewLabelMode(); this.disableAddNewLabelMode();
dispatch( dispatch(
actions.annotationCreateLabelInCategory( actions.annotationCreateLabelInCategory(
@@ -44,10 +49,11 @@ class Category extends React.PureComponent {
e.preventDefault(); e.preventDefault();
}; };
addLabelAndAssignCells = (e) => { 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 { dispatch, metadataField } = this.props;
const { newLabelText } = this.state; const { newLabelText } = this.state;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
this.disableAddNewLabelMode(); this.disableAddNewLabelMode();
dispatch( dispatch(
actions.annotationCreateLabelInCategory(metadataField, newLabelText, true) actions.annotationCreateLabelInCategory(metadataField, newLabelText, true)
@@ -55,26 +61,28 @@ class Category extends React.PureComponent {
e.preventDefault(); e.preventDefault();
}; };
labelNameError = (name) => { 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; const { metadataField, schema } = this.props;
return isLabelErroneous(name, metadataField, schema); return isLabelErroneous(name, metadataField, schema);
}; };
instruction = (label) => { instruction = (label: any) => {
return labelPrompt(this.labelNameError(label), "New, unique label", ":"); return labelPrompt(this.labelNameError(label), "New, unique label", ":");
}; };
handleChangeOrSelect = (label) => { handleChangeOrSelect = (label: any) => {
this.setState({ newLabelText: label }); this.setState({ newLabelText: label });
}; };
render() { render() {
const { newLabelText } = this.state; 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; const { metadataField, annotations, obsCrossfilter } = this.props;
return ( return (
<> <>
<AnnoDialog <AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; inputProps: { "data-testid"... Remove this comment to see the full error message
isActive={ isActive={
annotations.isAddingNewLabel && annotations.isAddingNewLabel &&
annotations.categoryAddingNewLabel === metadataField annotations.categoryAddingNewLabel === metadataField
@@ -95,6 +103,7 @@ class Category extends React.PureComponent {
handleCancel={this.disableAddNewLabelMode} handleCancel={this.disableAddNewLabelMode}
annoInput={ annoInput={
<LabelInput <LabelInput
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ labelSuggestions: null; onChange: (label: ... Remove this comment to see the full error message
labelSuggestions={null} labelSuggestions={null}
onChange={this.handleChangeOrSelect} onChange={this.handleChangeOrSelect}
onSelect={this.handleChangeOrSelect} onSelect={this.handleChangeOrSelect}
@@ -7,25 +7,30 @@ import { labelPrompt } from "../labelUtil";
import { AnnotationsHelpers } from "../../../util/stateManager"; import { AnnotationsHelpers } from "../../../util/stateManager";
import actions from "../../../actions"; import actions from "../../../actions";
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) => ({ @connect((state) => ({
annotations: state.annotations, annotations: (state as any).annotations,
schema: state.annoMatrix?.schema, schema: (state as any).annoMatrix?.schema,
})) }))
class AnnoDialogEditCategoryName extends React.PureComponent { class AnnoDialogEditCategoryName extends React.PureComponent<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { 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, newCategoryText: props.metadataField,
}; };
} }
handleChangeOrSelect = (name) => { handleChangeOrSelect = (name: any) => {
this.setState({ this.setState({
newCategoryText: name, newCategoryText: name,
}); });
}; };
disableEditCategoryMode = () => { 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; const { dispatch, metadataField } = this.props;
dispatch({ dispatch({
type: "annotation: disable category edit mode", type: "annotation: disable category edit mode",
@@ -33,17 +38,19 @@ class AnnoDialogEditCategoryName extends React.PureComponent {
this.setState({ newCategoryText: metadataField }); this.setState({ newCategoryText: metadataField });
}; };
handleEditCategory = (e) => { 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 { dispatch, metadataField } = this.props;
const { newCategoryText } = this.state; const { newCategoryText } = this.state;
/* /*
test for uniqueness against *all* annotation names, not just the subset test for uniqueness against *all* annotation names, not just the subset
we render as categorical. 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 { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); const allCategoryNames = schema.annotations.obs.columns.map(
(c: any) => c.name
);
if ( if (
(allCategoryNames.indexOf(newCategoryText) > -1 && (allCategoryNames.indexOf(newCategoryText) > -1 &&
newCategoryText !== metadataField) || newCategoryText !== metadataField) ||
@@ -51,9 +58,7 @@ class AnnoDialogEditCategoryName extends React.PureComponent {
) { ) {
return; return;
} }
this.disableEditCategoryMode(); this.disableEditCategoryMode();
if (metadataField !== newCategoryText) if (metadataField !== newCategoryText)
dispatch( dispatch(
actions.annotationRenameCategoryAction(metadataField, newCategoryText) actions.annotationRenameCategoryAction(metadataField, newCategoryText)
@@ -61,35 +66,34 @@ class AnnoDialogEditCategoryName extends React.PureComponent {
e.preventDefault(); e.preventDefault();
}; };
editedCategoryNameError = (name) => { 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; const { metadataField } = this.props;
/* check for syntax errors in category name */ /* check for syntax errors in category name */
const error = AnnotationsHelpers.annotationNameIsErroneous(name); const error = AnnotationsHelpers.annotationNameIsErroneous(name);
if (error) { if (error) {
return error; return error;
} }
/* check for duplicative categories */ /* check for duplicative categories */
/* /*
test for uniqueness against *all* annotation names, not just the subset test for uniqueness against *all* annotation names, not just the subset
we render as categorical. 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 { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); const allCategoryNames = schema.annotations.obs.columns.map(
(c: any) => c.name
);
const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1; const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1;
const sameName = name === metadataField; const sameName = name === metadataField;
if (categoryNameAlreadyExists && !sameName) { if (categoryNameAlreadyExists && !sameName) {
return "duplicate"; return "duplicate";
} }
/* otherwise, no error */ /* otherwise, no error */
return false; return false;
}; };
instruction = (name) => { instruction = (name: any) => {
return labelPrompt( return labelPrompt(
this.editedCategoryNameError(name), this.editedCategoryNameError(name),
"New, unique category name", "New, unique category name",
@@ -98,17 +102,19 @@ class AnnoDialogEditCategoryName extends React.PureComponent {
}; };
allCategoryNames() { 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; const { schema } = this.props;
return schema.annotations.obs.columns.map((c) => c.name); return schema.annotations.obs.columns.map((c: any) => c.name);
} }
render() { render() {
const { newCategoryText } = this.state; 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; const { metadataField, annotations } = this.props;
return ( return (
<> <>
<AnnoDialog <AnnoDialog
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ isActive: any; inputProps: { "data-testid"... Remove this comment to see the full error message
isActive={ isActive={
annotations.isEditingCategoryName && annotations.isEditingCategoryName &&
annotations.categoryBeingEdited === metadataField annotations.categoryBeingEdited === metadataField
@@ -129,6 +135,7 @@ class AnnoDialogEditCategoryName extends React.PureComponent {
handleCancel={this.disableEditCategoryMode} handleCancel={this.disableEditCategoryMode}
annoInput={ annoInput={
<LabelInput <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} label={newCategoryText}
labelSuggestions={null} labelSuggestions={null}
onChange={this.handleChangeOrSelect} onChange={this.handleChangeOrSelect}
@@ -16,16 +16,20 @@ import { IconNames } from "@blueprintjs/icons";
import * as globals from "../../../globals"; import * as globals from "../../../globals";
import actions from "../../../actions"; import actions from "../../../actions";
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) => ({ @connect((state) => ({
annotations: state.annotations, annotations: (state as any).annotations,
})) }))
class AnnoMenuCategory extends React.PureComponent { class AnnoMenuCategory extends React.PureComponent<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = {}; this.state = {};
} }
activateAddNewLabelMode = () => { 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; const { dispatch, metadataField } = this.props;
dispatch({ dispatch({
type: "annotation: activate add new label mode", type: "annotation: activate add new label mode",
@@ -34,8 +38,8 @@ class AnnoMenuCategory extends React.PureComponent {
}; };
activateEditCategoryMode = () => { 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; const { dispatch, metadataField } = this.props;
dispatch({ dispatch({
type: "annotation: activate category edit mode", type: "annotation: activate category edit mode",
data: metadataField, data: metadataField,
@@ -43,20 +47,26 @@ class AnnoMenuCategory extends React.PureComponent {
}; };
handleDeleteCategory = () => { 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; const { dispatch, metadataField } = this.props;
dispatch(actions.annotationDeleteCategoryAction(metadataField)); dispatch(actions.annotationDeleteCategoryAction(metadataField));
}; };
render() { render() {
const { 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, 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, 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, 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, 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, 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, deleteText,
} = this.props; } = this.props;
return ( return (
<> <>
{isUserAnno ? ( {isUserAnno ? (
@@ -31,33 +31,39 @@ const LABEL_WIDTH = globals.leftSidebarWidth - 100;
const ANNO_BUTTON_WIDTH = 50; const ANNO_BUTTON_WIDTH = 50;
const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH; 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) => { @connect((state, ownProps) => {
const schema = state.annoMatrix?.schema; 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 { metadataField } = ownProps;
const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable; const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable;
const categoricalSelection = state.categoricalSelection?.[metadataField]; const categoricalSelection = (state as any).categoricalSelection?.[
metadataField
];
return { return {
colors: state.colors, colors: (state as any).colors,
categoricalSelection, categoricalSelection,
annotations: state.annotations, annotations: (state as any).annotations,
annoMatrix: state.annoMatrix, annoMatrix: (state as any).annoMatrix,
schema, schema,
crossfilter: state.obsCrossfilter, crossfilter: (state as any).obsCrossfilter,
isUserAnno, isUserAnno,
genesets: state.genesets.genesets, genesets: (state as any).genesets.genesets,
}; };
}) })
class Category extends React.PureComponent { class Category extends React.PureComponent {
static getSelectionState( static getSelectionState(
categoricalSelection, categoricalSelection: any,
metadataField, // @ts-expect-error ts-migrate(6133) FIXME: 'metadataField' is declared but its value is never... Remove this comment to see the full error message
categorySummary metadataField: any,
categorySummary: any
) { ) {
// total number of categories in this dimension // total number of categories in this dimension
const totalCatCount = categorySummary.numCategoryValues; const totalCatCount = categorySummary.numCategoryValues;
// number of selected options in this category // number of selected options in this category
const selectedCatCount = categorySummary.categoryValues.reduce( const selectedCatCount = categorySummary.categoryValues.reduce(
(res, label) => (categoricalSelection.get(label) ?? true ? res + 1 : res), (res: any, label: any) =>
categoricalSelection.get(label) ?? true ? res + 1 : res,
0 0
); );
return selectedCatCount === totalCatCount return selectedCatCount === totalCatCount
@@ -67,13 +73,14 @@ class Category extends React.PureComponent {
: "some"; : "some";
} }
static watchAsync(props, prevProps) { static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps); return !shallowEqual(props.watchProps, prevProps.watchProps);
} }
createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol); createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol);
getSelectionState(categorySummary) { 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; const { categoricalSelection, metadataField } = this.props;
return Category.getSelectionState( return Category.getSelectionState(
categoricalSelection, categoricalSelection,
@@ -83,6 +90,7 @@ class Category extends React.PureComponent {
} }
handleColorChange = () => { 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; const { dispatch, metadataField } = this.props;
dispatch({ dispatch({
type: "color by categorical metadata", type: "color by categorical metadata",
@@ -91,6 +99,7 @@ class Category extends React.PureComponent {
}; };
handleCategoryClick = () => { 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 { annotations, metadataField, onExpansionChange } = this.props;
const editingCategory = const editingCategory =
annotations.isEditingCategoryName && annotations.isEditingCategoryName &&
@@ -100,13 +109,13 @@ class Category extends React.PureComponent {
} }
}; };
handleCategoryKeyPress = (e) => { handleCategoryKeyPress = (e: any) => {
if (e.key === "Enter") { if (e.key === "Enter") {
this.handleCategoryClick(); this.handleCategoryClick();
} }
}; };
handleToggleAllClick = (categorySummary) => { handleToggleAllClick = (categorySummary: any) => {
const isChecked = this.getSelectionState(categorySummary); const isChecked = this.getSelectionState(categorySummary);
if (isChecked === "all") { if (isChecked === "all") {
this.toggleNone(categorySummary); this.toggleNone(categorySummary);
@@ -115,8 +124,9 @@ class Category extends React.PureComponent {
} }
}; };
fetchAsyncProps = async (props) => { fetchAsyncProps = async (props: any) => {
const { annoMatrix, metadataField, colors } = props.watchProps; 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 { crossfilter } = this.props;
const [categoryData, categorySummary, colorData] = await this.fetchData( const [categoryData, categorySummary, colorData] = await this.fetchData(
@@ -136,13 +146,14 @@ class Category extends React.PureComponent {
}; };
}; };
async fetchData(annoMatrix, metadataField, colors) { async fetchData(annoMatrix: any, metadataField: any, colors: any) {
/* /*
fetch our data and the color-by data if appropriate, and then build a summary 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. of our category and a color table for the color-by annotation.
*/ */
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorAccessor, colorMode } = colors; 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; const { genesets } = this.props;
let colorDataPromise = Promise.resolve(null); let colorDataPromise = Promise.resolve(null);
if (colorAccessor) { if (colorAccessor) {
@@ -169,8 +180,9 @@ class Category extends React.PureComponent {
return [categoryData, categorySummary, colorData]; return [categoryData, categorySummary, colorData];
} }
updateColorTable(colorData) { updateColorTable(colorData: any) {
// color table, which may be 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 { schema, colors, metadataField } = this.props;
const { colorAccessor, userColors, colorMode } = colors; const { colorAccessor, userColors, colorMode } = colors;
return { return {
@@ -187,7 +199,8 @@ class Category extends React.PureComponent {
}; };
} }
toggleNone(categorySummary) { 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; const { dispatch, metadataField } = this.props;
dispatch( dispatch(
actions.selectCategoricalAllMetadataAction( actions.selectCategoricalAllMetadataAction(
@@ -199,7 +212,8 @@ class Category extends React.PureComponent {
); );
} }
toggleAll(categorySummary) { 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; const { dispatch, metadataField } = this.props;
dispatch( dispatch(
actions.selectCategoricalAllMetadataAction( actions.selectCategoricalAllMetadataAction(
@@ -213,12 +227,19 @@ class Category extends React.PureComponent {
render() { render() {
const { 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, 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, isExpanded,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
categoricalSelection, 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, 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, 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, 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, isUserAnno,
} = this.props; } = this.props;
@@ -250,18 +271,26 @@ class Category extends React.PureComponent {
<Async.Fulfilled persist> <Async.Fulfilled persist>
{(asyncProps) => { {(asyncProps) => {
const { 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, 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, 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, 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, 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, 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, isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCategoryToggleAllClick' does not e... Remove this comment to see the full error message
handleCategoryToggleAllClick, handleCategoryToggleAllClick,
} = asyncProps; } = asyncProps;
const isTruncated = !!categorySummary?.isTruncated; const isTruncated = !!categorySummary?.isTruncated;
const selectionState = this.getSelectionState(categorySummary); const selectionState = this.getSelectionState(categorySummary);
return ( return (
<CategoryRender <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} metadataField={metadataField}
checkboxID={checkboxID} checkboxID={checkboxID}
isUserAnno={isUserAnno} isUserAnno={isUserAnno}
@@ -290,7 +319,7 @@ class Category extends React.PureComponent {
export default Category; export default Category;
const StillLoading = ({ metadataField, checkboxID }) => { const StillLoading = ({ metadataField, checkboxID }: any) => {
/* /*
We are still loading this category, so render a "busy" signal. We are still loading this category, so render a "busy" signal.
*/ */
@@ -341,7 +370,7 @@ const StillLoading = ({ metadataField, checkboxID }) => {
); );
}; };
const ErrorLoading = ({ metadataField, error }) => { const ErrorLoading = ({ metadataField, error }: any) => {
console.error(error); // log error to console as it is unexpected. console.error(error); // log error to console as it is unexpected.
return ( return (
<div style={{ marginBottom: 10, marginTop: 4 }}> <div style={{ marginBottom: 10, marginTop: 4 }}>
@@ -361,16 +390,27 @@ const ErrorLoading = ({ metadataField, error }) => {
const CategoryHeader = React.memo( 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, 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, 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, isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isTruncated' does not exist on type '{ c... Remove this comment to see the full error message
isTruncated, isTruncated,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor, 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, 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, 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, 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, onCategoryMenuClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message
onCategoryMenuKeyPress, onCategoryMenuKeyPress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message
onCategoryToggleAllClick, onCategoryToggleAllClick,
}) => { }) => {
/* /*
@@ -379,6 +419,7 @@ const CategoryHeader = React.memo(
const checkboxRef = useRef(null); const checkboxRef = useRef(null);
useEffect(() => { useEffect(() => {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
checkboxRef.current.indeterminate = selectionState === "some"; checkboxRef.current.indeterminate = selectionState === "some";
}, [checkboxRef.current, selectionState]); }, [checkboxRef.current, selectionState]);
@@ -408,6 +449,7 @@ const CategoryHeader = React.memo(
</label> </label>
<span <span
role="menuitem" 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" tabIndex="0"
data-testclass="category-expand" data-testclass="category-expand"
data-testid={`${metadataField}:category-expand`} data-testid={`${metadataField}:category-expand`}
@@ -423,6 +465,7 @@ const CategoryHeader = React.memo(
maxWidth: isUserAnno ? LABEL_WIDTH_ANNO : LABEL_WIDTH, maxWidth: isUserAnno ? LABEL_WIDTH_ANNO : LABEL_WIDTH,
}} }}
data-testid={`${metadataField}:category-label`} 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" tabIndex="-1"
> >
{metadataField} {metadataField}
@@ -441,10 +484,13 @@ const CategoryHeader = React.memo(
)} )}
</span> </span>
</div> </div>
{<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} />} <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> <div>
<AnnoMenu <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} metadataField={metadataField}
isUserAnno={isUserAnno} isUserAnno={isUserAnno}
createText="Add a new label to this category" createText="Add a new label to this category"
@@ -484,21 +530,37 @@ const CategoryHeader = React.memo(
const CategoryRender = React.memo( 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, 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, 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, isUserAnno,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isTruncated' does not exist on type '{ c... Remove this comment to see the full error message
isTruncated, isTruncated,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message
isColorAccessor, 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, 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, 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, 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, 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, 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, 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, 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, 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, onCategoryMenuClick,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message
onCategoryMenuKeyPress, onCategoryMenuKeyPress,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message
onCategoryToggleAllClick, onCategoryToggleAllClick,
}) => { }) => {
/* /*
@@ -533,6 +595,7 @@ const CategoryRender = React.memo(
}} }}
> >
<CategoryHeader <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} metadataField={metadataField}
checkboxID={checkboxID} checkboxID={checkboxID}
isUserAnno={isUserAnno} isUserAnno={isUserAnno}
@@ -551,6 +614,7 @@ const CategoryRender = React.memo(
/* values*/ /* values*/
isExpanded ? ( isExpanded ? (
<CategoryValueList <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} isUserAnno={isUserAnno}
metadataField={metadataField} metadataField={metadataField}
categoryData={categoryData} categoryData={categoryData}
@@ -574,12 +638,19 @@ const CategoryRender = React.memo(
const CategoryValueList = React.memo( 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, 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, 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, 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, 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, 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, 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, colorTable,
}) => { }) => {
const tuples = [...categorySummary.categoryValueIndices]; const tuples = [...categorySummary.categoryValueIndices];
@@ -594,6 +665,7 @@ const CategoryValueList = React.memo(
{tuples.map(([value, index]) => ( {tuples.map(([value, index]) => (
<Value <Value
key={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} isUserAnno={isUserAnno}
metadataField={metadataField} metadataField={metadataField}
categoryIndex={index} categoryIndex={index}
@@ -615,6 +687,7 @@ const CategoryValueList = React.memo(
{tuples.map(([value, index]) => ( {tuples.map(([value, index]) => (
<Flipped key={value} flipId={value}> <Flipped key={value} flipId={value}>
<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} isUserAnno={isUserAnno}
metadataField={metadataField} metadataField={metadataField}
categoryIndex={index} categoryIndex={index}
@@ -10,13 +10,17 @@ import LabelInput from "../labelInput";
import { labelPrompt } from "./labelUtil"; import { labelPrompt } from "./labelUtil";
import actions from "../../actions"; import actions from "../../actions";
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) => ({ @connect((state) => ({
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, writableCategoriesEnabled:
schema: state.annoMatrix?.schema, (state as any).config?.parameters?.annotations ?? false,
userInfo: state.userInfo, schema: (state as any).annoMatrix?.schema,
userInfo: (state as any).userInfo,
})) }))
class Categories extends React.Component { class Categories extends React.Component<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
createAnnoModeActive: false, createAnnoModeActive: false,
@@ -26,7 +30,8 @@ class Categories extends React.Component {
}; };
} }
handleCreateUserAnno = (e) => { 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
const { dispatch } = this.props; const { dispatch } = this.props;
const { newCategoryText, categoryToDuplicate } = this.state; const { newCategoryText, categoryToDuplicate } = this.state;
dispatch( dispatch(
@@ -55,50 +60,48 @@ class Categories extends React.Component {
}); });
}; };
handleModalDuplicateCategorySelection = (d) => { handleModalDuplicateCategorySelection = (d: any) => {
this.setState({ categoryToDuplicate: d }); this.setState({ categoryToDuplicate: d });
}; };
categoryNameError = (name) => { categoryNameError = (name: any) => {
/* /*
return false if this is a LEGAL/acceptable category name or NULL/empty string, return false if this is a LEGAL/acceptable category name or NULL/empty string,
or return an error type. or return an error type.
*/ */
/* allow empty string */ /* allow empty string */
if (name === "") return false; if (name === "") return false;
/* /*
test for uniqueness against *all* annotation names, not just the subset test for uniqueness against *all* annotation names, not just the subset
we render as categorical. 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 { schema } = this.props;
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); const allCategoryNames = schema.annotations.obs.columns.map(
(c: any) => c.name
);
/* check category name syntax */ /* check category name syntax */
const error = AnnotationsHelpers.annotationNameIsErroneous(name); const error = AnnotationsHelpers.annotationNameIsErroneous(name);
if (error) { if (error) {
return error; return error;
} }
/* disallow duplicates */ /* disallow duplicates */
if (allCategoryNames.indexOf(name) !== -1) { if (allCategoryNames.indexOf(name) !== -1) {
return "duplicate"; return "duplicate";
} }
/* otherwise, no error */ /* otherwise, no error */
return false; return false;
}; };
handleChange = (name) => { handleChange = (name: any) => {
this.setState({ newCategoryText: name }); this.setState({ newCategoryText: name });
}; };
handleSelect = (name) => { handleSelect = (name: any) => {
this.setState({ newCategoryText: name }); this.setState({ newCategoryText: name });
}; };
instruction = (name) => { instruction = (name: any) => {
return labelPrompt( return labelPrompt(
this.categoryNameError(name), this.categoryNameError(name),
"New, unique category name", "New, unique category name",
@@ -106,7 +109,7 @@ class Categories extends React.Component {
); );
}; };
onExpansionChange = (catName) => { onExpansionChange = (catName: any) => {
const { expandedCats } = this.state; const { expandedCats } = this.state;
if (expandedCats.has(catName)) { if (expandedCats.has(catName)) {
const _expandedCats = new Set(expandedCats); const _expandedCats = new Set(expandedCats);
@@ -126,16 +129,13 @@ class Categories extends React.Component {
newCategoryText, newCategoryText,
expandedCats, expandedCats,
} = this.state; } = this.state;
const { // @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message
writableCategoriesEnabled, const { writableCategoriesEnabled, schema, userInfo } = this.props;
schema,
userInfo,
} = this.props;
/* all names, sorted in display order. Will be rendered in this order */ /* 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( const allCategoryNames = ControlsHelpers.selectableCategoryNames(
schema schema
).sort(); ).sort();
return ( return (
<div <div
style={{ style={{
@@ -143,6 +143,7 @@ class Categories extends React.Component {
}} }}
> >
<AnnoDialog <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} isActive={createAnnoModeActive}
title="Create new category" title="Create new category"
instruction={this.instruction(newCategoryText)} instruction={this.instruction(newCategoryText)}
@@ -155,6 +156,7 @@ class Categories extends React.Component {
handleCancel={this.handleDisableAnnoMode} handleCancel={this.handleDisableAnnoMode}
annoInput={ annoInput={
<LabelInput <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} labelSuggestions={null}
onChange={this.handleChange} onChange={this.handleChange}
onSelect={this.handleSelect} onSelect={this.handleSelect}
@@ -169,6 +171,7 @@ class Categories extends React.Component {
} }
annoSelect={ annoSelect={
<AnnoSelect <AnnoSelect
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ handleModalDuplicateCategorySelection: (d:... Remove this comment to see the full error message
handleModalDuplicateCategorySelection={ handleModalDuplicateCategorySelection={
this.handleModalDuplicateCategorySelection this.handleModalDuplicateCategorySelection
} }
@@ -209,12 +212,13 @@ class Categories extends React.Component {
{/* READ ONLY CATEGORICAL FIELDS */} {/* READ ONLY CATEGORICAL FIELDS */}
{/* this is duplicative but flat, could be abstracted */} {/* this is duplicative but flat, could be abstracted */}
{allCategoryNames.map((catName) => {allCategoryNames.map((catName: any) =>
!schema.annotations.obsByName[catName].writable && !schema.annotations.obsByName[catName].writable &&
(schema.annotations.obsByName[catName].categories?.length > 1 || (schema.annotations.obsByName[catName].categories?.length > 1 ||
!schema.annotations.obsByName[catName].categories) ? ( !schema.annotations.obsByName[catName].categories) ? (
<Category <Category
key={catName} key={catName}
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
metadataField={catName} metadataField={catName}
onExpansionChange={this.onExpansionChange} onExpansionChange={this.onExpansionChange}
isExpanded={expandedCats.has(catName)} isExpanded={expandedCats.has(catName)}
@@ -223,10 +227,11 @@ class Categories extends React.Component {
) : null ) : null
)} )}
{/* WRITEABLE FIELDS */} {/* WRITEABLE FIELDS */}
{allCategoryNames.map((catName) => {allCategoryNames.map((catName: any) =>
schema.annotations.obsByName[catName].writable ? ( schema.annotations.obsByName[catName].writable ? (
<Category <Category
key={catName} key={catName}
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
metadataField={catName} metadataField={catName}
onExpansionChange={this.onExpansionChange} onExpansionChange={this.onExpansionChange}
isExpanded={expandedCats.has(catName)} isExpanded={expandedCats.has(catName)}
@@ -3,7 +3,7 @@ import { Colors } from "@blueprintjs/core";
import { AnnotationsHelpers } from "../../util/stateManager"; import { AnnotationsHelpers } from "../../util/stateManager";
export function isLabelErroneous(label, metadataField, schema) { export function isLabelErroneous(label: any, metadataField: any, schema: any) {
/* /*
return false if this is a LEGAL/acceptable category name or NULL/empty string, return false if this is a LEGAL/acceptable category name or NULL/empty string,
or return an error type. or return an error type.
@@ -35,9 +35,10 @@ const errorMessageMap = {
"multi-space-run": "Multiple consecutive spaces not allowed", "multi-space-run": "Multiple consecutive spaces not allowed",
}; };
export function labelPrompt(err, prolog, epilog) { export function labelPrompt(err: any, prolog: any, epilog: any) {
let errPrompt = null; let errPrompt = null;
if (err) { 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"; let errMsg = errorMessageMap[err] ?? "error";
errMsg = errMsg[0].toLowerCase() + errMsg.slice(1); errMsg = errMsg[0].toLowerCase() + errMsg.slice(1);
errPrompt = ( errPrompt = (
@@ -13,6 +13,7 @@ import {
Position, Position,
} from "@blueprintjs/core"; } from "@blueprintjs/core";
import * as globals from "../../../globals"; 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 styles from "../categorical.css";
import AnnoDialog from "../../annoDialog"; import AnnoDialog from "../../annoDialog";
import LabelInput from "../../labelInput"; import LabelInput from "../../labelInput";
@@ -29,15 +30,20 @@ const STACKED_BAR_HEIGHT = 11;
const STACKED_BAR_WIDTH = 100; const STACKED_BAR_WIDTH = 100;
/* this is defined outside of the class so we can use it in connect() */ /* this is defined outside of the class so we can use it in connect() */
function _currentLabelAsString(ownProps) { function _currentLabelAsString(ownProps: any) {
const { label } = ownProps; const { label } = ownProps;
// when called as a function, the String() constructor performs type conversion, // when called as a function, the String() constructor performs type conversion,
// and returns a primitive string. // and returns a primitive string.
return String(label); return String(label);
} }
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) => { @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; 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 { metadataField, categorySummary, categoryIndex } = ownProps;
const isDilated = const isDilated =
pointDilation.metadataField === metadataField && pointDilation.metadataField === metadataField &&
@@ -48,27 +54,28 @@ function _currentLabelAsString(ownProps) {
const isSelected = category.get(label) ?? true; const isSelected = category.get(label) ?? true;
return { return {
annotations: state.annotations, annotations: (state as any).annotations,
schema: state.annoMatrix?.schema, schema: (state as any).annoMatrix?.schema,
isDilated, isDilated,
isSelected, isSelected,
label, label,
}; };
}) })
class CategoryValue extends React.Component { class CategoryValue extends React.Component<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
editedLabelText: this.currentLabelAsString(), editedLabelText: this.currentLabelAsString(),
}; };
} }
componentDidUpdate(prevProps) { 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
const { metadataField, categoryIndex, categorySummary } = this.props; const { metadataField, categoryIndex, categorySummary } = this.props;
if ( if (
prevProps.metadataField !== metadataField || (prevProps as any).metadataField !== metadataField ||
prevProps.categoryIndex !== categoryIndex || (prevProps as any).categoryIndex !== categoryIndex ||
prevProps.categorySummary !== categorySummary (prevProps as any).categorySummary !== categorySummary
) { ) {
// eslint-disable-next-line react/no-did-update-set-state --- adequately checked to prevent looping // eslint-disable-next-line react/no-did-update-set-state --- adequately checked to prevent looping
this.setState({ this.setState({
@@ -79,22 +86,26 @@ class CategoryValue extends React.Component {
// If coloring by and this isn't the colorAccessor and it isn't being edited // If coloring by and this isn't the colorAccessor and it isn't being edited
get shouldRenderStackedBarOrHistogram() { 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; const { colorAccessor, isColorBy, annotations } = this.props;
return !!colorAccessor && !isColorBy && !annotations.isEditingLabelName; return !!colorAccessor && !isColorBy && !annotations.isEditingLabelName;
} }
handleDeleteValue = () => { 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; const { dispatch, metadataField, label } = this.props;
dispatch(actions.annotationDeleteLabelFromCategory(metadataField, label)); dispatch(actions.annotationDeleteLabelFromCategory(metadataField, label));
}; };
handleAddCurrentSelectionToThisLabel = () => { 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; const { dispatch, metadataField, label } = this.props;
dispatch(actions.annotationLabelCurrentSelection(metadataField, label)); dispatch(actions.annotationLabelCurrentSelection(metadataField, label));
}; };
handleEditValue = (e) => { 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
const { dispatch, metadataField, label } = this.props; const { dispatch, metadataField, label } = this.props;
const { editedLabelText } = this.state; const { editedLabelText } = this.state;
this.cancelEditMode(); this.cancelEditMode();
@@ -108,7 +119,8 @@ class CategoryValue extends React.Component {
e.preventDefault(); e.preventDefault();
}; };
handleCreateArbitraryLabel = (txt) => { 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
const { dispatch, metadataField, label } = this.props; const { dispatch, metadataField, label } = this.props;
this.cancelEditMode(); this.cancelEditMode();
dispatch( dispatch(
@@ -116,17 +128,19 @@ class CategoryValue extends React.Component {
); );
}; };
labelNameError = (name) => { 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; const { metadataField, schema } = this.props;
if (name === this.currentLabelAsString()) return false; if (name === this.currentLabelAsString()) return false;
return isLabelErroneous(name, metadataField, schema); return isLabelErroneous(name, metadataField, schema);
}; };
instruction = (label) => { instruction = (label: any) => {
return labelPrompt(this.labelNameError(label), "New, unique label", ":"); return labelPrompt(this.labelNameError(label), "New, unique label", ":");
}; };
activateEditLabelMode = () => { 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; const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({ dispatch({
type: "annotation: activate edit label mode", type: "annotation: activate edit label mode",
@@ -137,6 +151,7 @@ class CategoryValue extends React.Component {
}; };
cancelEditMode = () => { 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; const { dispatch, metadataField, categoryIndex, label } = this.props;
this.setState({ this.setState({
editedLabelText: this.currentLabelAsString(), editedLabelText: this.currentLabelAsString(),
@@ -151,9 +166,13 @@ class CategoryValue extends React.Component {
toggleOff = () => { toggleOff = () => {
const { 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, 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, 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, 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, categorySummary,
} = this.props; } = this.props;
const label = categorySummary.categoryValues[categoryIndex]; const label = categorySummary.categoryValues[categoryIndex];
@@ -168,7 +187,7 @@ class CategoryValue extends React.Component {
); );
}; };
shouldComponentUpdate = (nextProps, nextState) => { shouldComponentUpdate = (nextProps: any, nextState: any) => {
/* /*
Checks to see if at least one of the following changed: Checks to see if at least one of the following changed:
* world state * world state
@@ -179,6 +198,7 @@ class CategoryValue extends React.Component {
If and only if true, update the component If and only if true, update the component
*/ */
const { props, state } = this; 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, categorySummary, isSelected } = props;
const { const {
categoryIndex: newCategoryIndex, categoryIndex: newCategoryIndex,
@@ -191,10 +211,12 @@ class CategoryValue extends React.Component {
const labelChanged = label !== newLabel; const labelChanged = label !== newLabel;
const valueSelectionChange = isSelected !== newIsSelected; const valueSelectionChange = isSelected !== newIsSelected;
const colorAccessorChange = props.colorAccessor !== nextProps.colorAccessor; const colorAccessorChange =
const annotationsChange = props.annotations !== nextProps.annotations; (props as any).colorAccessor !== nextProps.colorAccessor;
const annotationsChange =
(props as any).annotations !== nextProps.annotations;
const editingLabel = state.editedLabelText !== nextState.editedLabelText; const editingLabel = state.editedLabelText !== nextState.editedLabelText;
const dilationChange = props.isDilated !== nextProps.isDilated; const dilationChange = (props as any).isDilated !== nextProps.isDilated;
const count = categorySummary.categoryValueCounts[categoryIndex]; const count = categorySummary.categoryValueCounts[categoryIndex];
const newCount = newCategorySummary.categoryValueCounts[newCategoryIndex]; const newCount = newCategorySummary.categoryValueCounts[newCategoryIndex];
@@ -205,7 +227,7 @@ class CategoryValue extends React.Component {
// if any one changes, but only for the currently colored-by category. // if any one changes, but only for the currently colored-by category.
const colorMightHaveChanged = const colorMightHaveChanged =
nextProps.colorAccessor === nextProps.metadataField && nextProps.colorAccessor === nextProps.metadataField &&
props.categorySummary !== nextProps.categorySummary; (props as any).categorySummary !== nextProps.categorySummary;
return ( return (
labelChanged || labelChanged ||
@@ -221,9 +243,13 @@ class CategoryValue extends React.Component {
toggleOn = () => { toggleOn = () => {
const { 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, 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, 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, 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, categorySummary,
} = this.props; } = this.props;
const label = categorySummary.categoryValues[categoryIndex]; const label = categorySummary.categoryValues[categoryIndex];
@@ -239,6 +265,7 @@ class CategoryValue extends React.Component {
}; };
handleMouseEnter = () => { 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; const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({ dispatch({
type: "category value mouse hover start", type: "category value mouse hover start",
@@ -249,6 +276,7 @@ class CategoryValue extends React.Component {
}; };
handleMouseExit = () => { 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; const { dispatch, metadataField, categoryIndex, label } = this.props;
dispatch({ dispatch({
type: "category value mouse hover end", type: "category value mouse hover end",
@@ -258,23 +286,24 @@ class CategoryValue extends React.Component {
}); });
}; };
handleTextChange = (text) => { handleTextChange = (text: any) => {
this.setState({ editedLabelText: text }); this.setState({ editedLabelText: text });
}; };
handleChoice = (e) => { handleChoice = (e: any) => {
/* Blueprint Suggest format */ /* Blueprint Suggest format */
this.setState({ editedLabelText: e.target }); this.setState({ editedLabelText: e.target });
}; };
createHistogramBins = ( createHistogramBins = (
metadataField, metadataField: any,
categoryData, categoryData: any,
colorAccessor, // @ts-expect-error ts-migrate(6133) FIXME: 'colorAccessor' is declared but its value is never... Remove this comment to see the full error message
colorData, colorAccessor: any,
categoryValue, colorData: any,
width, categoryValue: any,
height width: any,
height: any
) => { ) => {
/* /*
Knowing that colorScale is based off continuous data, Knowing that colorScale is based off continuous data,
@@ -309,14 +338,15 @@ class CategoryValue extends React.Component {
}; };
createStackedGraphBins = ( createStackedGraphBins = (
metadataField, metadataField: any,
categoryData, categoryData: any,
colorAccessor, colorAccessor: any,
colorData, colorData: any,
categoryValue, categoryValue: any,
colorTable, // @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
schema, colorTable: any,
width schema: any,
width: any
) => { ) => {
/* /*
Knowing that the color scale is based off of categorical data, Knowing that the color scale is based off of categorical data,
@@ -357,12 +387,13 @@ class CategoryValue extends React.Component {
return _currentLabelAsString(this.props); return _currentLabelAsString(this.props);
} }
isAddCurrentSelectionDisabled(crossfilter, category, value) { isAddCurrentSelectionDisabled(crossfilter: any, category: any, value: any) {
/* /*
disable "add current selection to label", if one of the following is true: disable "add current selection to label", if one of the following is true:
1. no cells are selected 1. no cells are selected
2. all currently selected cells already have this label, on this category 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; const { categoryData } = this.props;
// 1. no cells selected? // 1. no cells selected?
@@ -382,12 +413,19 @@ class CategoryValue extends React.Component {
renderMiniStackedBar = () => { renderMiniStackedBar = () => {
const { 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, 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, 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, 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, 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, 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, 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, label,
} = this.props; } = this.props;
const isColorBy = metadataField === colorAccessor; const isColorBy = metadataField === colorAccessor;
@@ -425,6 +463,7 @@ class CategoryValue extends React.Component {
domain, domain,
occupancy, 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} height={STACKED_BAR_HEIGHT}
width={STACKED_BAR_WIDTH} width={STACKED_BAR_WIDTH}
/> />
@@ -433,12 +472,19 @@ class CategoryValue extends React.Component {
renderMiniHistogram = () => { renderMiniHistogram = () => {
const { 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, 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, 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, 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, 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, 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, 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, label,
} = this.props; } = this.props;
const colorScale = colorTable?.scale; const colorScale = colorTable?.scale;
@@ -473,6 +519,7 @@ class CategoryValue extends React.Component {
yScale, yScale,
bins, bins,
}} }}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ obsOrVarContinuousFieldDisplayName: any; d... Remove this comment to see the full error message
obsOrVarContinuousFieldDisplayName={colorAccessor} obsOrVarContinuousFieldDisplayName={colorAccessor}
domainLabel={label} domainLabel={label}
height={STACKED_BAR_HEIGHT} height={STACKED_BAR_HEIGHT}
@@ -483,15 +530,25 @@ class CategoryValue extends React.Component {
render() { render() {
const { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, label,
} = this.props; } = this.props;
const colorScale = colorTable?.scale; const colorScale = colorTable?.scale;
@@ -587,6 +644,7 @@ class CategoryValue extends React.Component {
<span <span
data-testid={`categorical-value-${metadataField}-${displayString}`} data-testid={`categorical-value-${metadataField}-${displayString}`}
data-testclass="categorical-value" 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" tabIndex="-1"
style={{ style={{
width: labelWidth, width: labelWidth,
@@ -612,6 +670,7 @@ class CategoryValue extends React.Component {
{editModeActive ? ( {editModeActive ? (
<div> <div>
<AnnoDialog <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} isActive={editModeActive}
inputProps={{ inputProps={{
"data-testid": `${metadataField}:edit-label-name-dialog`, "data-testid": `${metadataField}:edit-label-name-dialog`,
@@ -630,6 +689,7 @@ class CategoryValue extends React.Component {
handleCancel={this.cancelEditMode} handleCancel={this.cancelEditMode}
annoInput={ annoInput={
<LabelInput <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} label={editedLabelText}
labelSuggestions={null} labelSuggestions={null}
onChange={this.handleTextChange} onChange={this.handleTextChange}
@@ -8,64 +8,59 @@ import {
Position, Position,
} from "@blueprintjs/core"; } from "@blueprintjs/core";
// @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) => ({ @connect((state) => ({
schema: state.annoMatrix?.schema, schema: (state as any).annoMatrix?.schema,
})) }))
class Occupancy extends React.PureComponent { class Occupancy extends React.PureComponent {
canvas: any;
_WIDTH = 100; _WIDTH = 100;
_HEIGHT = 11; _HEIGHT = 11;
createHistogram = () => { createHistogram = () => {
/* /*
Knowing that colorScale is based off continous data, Knowing that colorScale is based off continous data,
createHistogram fetches the continous data in relation to the cells releveant to the catagory value. 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 It then seperates that data into 50 bins for drawing the mini-histogram
*/ */
const { 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, 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, 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, colorData,
// @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, categoryValue,
} = this.props; } = this.props;
if (!this.canvas) return; if (!this.canvas) return;
const groupBy = categoryData.col(metadataField); const groupBy = categoryData.col(metadataField);
const col = colorData.icol(0); const col = colorData.icol(0);
const range = col.summarize(); const range = col.summarize();
const histogramMap = col.histogram( const histogramMap = col.histogram(
50, 50,
[range.min, range.max], [range.min, range.max],
groupBy groupBy
); /* Because the signature changes we really need different names for histogram to differentiate signatures */ ); /* Because the signature changes we really need different names for histogram to differentiate signatures */
const bins = histogramMap.has(categoryValue) const bins = histogramMap.has(categoryValue)
? histogramMap.get(categoryValue) ? histogramMap.get(categoryValue)
: new Array(50).fill(0); : new Array(50).fill(0);
const xScale = d3 const xScale = d3
.scaleLinear() .scaleLinear()
.domain([0, bins.length]) .domain([0, bins.length])
.range([0, this._WIDTH]); .range([0, this._WIDTH]);
const largestBin = Math.max(...bins); const largestBin = Math.max(...bins);
const yScale = d3 const yScale = d3
.scaleLinear() .scaleLinear()
.domain([0, largestBin]) .domain([0, largestBin])
.range([0, this._HEIGHT]); .range([0, this._HEIGHT]);
const ctx = this.canvas.getContext("2d"); const ctx = this.canvas.getContext("2d");
ctx.fillStyle = "#000"; ctx.fillStyle = "#000";
let x; let x;
let y; let y;
const rectWidth = this._WIDTH / bins.length; const rectWidth = this._WIDTH / bins.length;
for (let i = 0, { length } = bins; i < length; i += 1) { for (let i = 0, { length } = bins; i < length; i += 1) {
x = xScale(i); x = xScale(i);
y = yScale(bins[i]); y = yScale(bins[i]);
@@ -75,32 +70,34 @@ class Occupancy extends React.PureComponent {
createOccupancyStack = () => { createOccupancyStack = () => {
/* /*
Knowing that the color scale is based off of catagorical data, Knowing that the color scale is based off of catagorical data,
createOccupancyStack obtains a map showing the number if cells per colored value 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 Using the colorScale a stack of colored bars is drawn representing the map
*/ */
const { 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, 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, categoryData,
// @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, colorAccessor,
// @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, categoryValue,
// @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, 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, schema,
// @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, colorData,
} = this.props; } = this.props;
const { scale: colorScale } = colorTable; const { scale: colorScale } = colorTable;
const ctx = this.canvas?.getContext("2d"); const ctx = this.canvas?.getContext("2d");
if (!ctx) return; if (!ctx) return;
const groupBy = categoryData.col(metadataField); const groupBy = categoryData.col(metadataField);
const occupancyMap = colorData const occupancyMap = colorData
.col(colorAccessor) .col(colorAccessor)
.histogramCategorical(groupBy); .histogramCategorical(groupBy);
const occupancy = occupancyMap.get(categoryValue); const occupancy = occupancyMap.get(categoryValue);
if (occupancy && occupancy.size > 0) { if (occupancy && occupancy.size > 0) {
// not all categories have occupancy, so occupancy may be undefined. // not all categories have occupancy, so occupancy may be undefined.
const x = d3 const x = d3
@@ -110,15 +107,12 @@ class Occupancy extends React.PureComponent {
.range([0, this._WIDTH]); .range([0, this._WIDTH]);
const categories = const categories =
schema.annotations.obsByName[colorAccessor]?.categories; schema.annotations.obsByName[colorAccessor]?.categories;
let currentOffset = 0; let currentOffset = 0;
const dfColumn = colorData.col(colorAccessor); const dfColumn = colorData.col(colorAccessor);
const categoryValues = dfColumn.summarizeCategorical().categories; const categoryValues = dfColumn.summarizeCategorical().categories;
let o; let o;
let scaledValue; let scaledValue;
let value; let value;
for (let i = 0, { length } = categoryValues; i < length; i += 1) { for (let i = 0, { length } = categoryValues; i < length; i += 1) {
value = categoryValues[i]; value = categoryValues[i];
o = occupancy.get(value); o = occupancy.get(value);
@@ -133,11 +127,11 @@ class Occupancy extends React.PureComponent {
}; };
render() { 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 { colorAccessor, categoryValue, colorByIsCategorical } = this.props;
const { canvas } = this; const { canvas } = this;
if (canvas) if (canvas)
canvas.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT); canvas.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT);
return ( return (
<Popover <Popover
interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY} interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}
@@ -1,32 +0,0 @@
/* 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;
@@ -0,0 +1,34 @@
/* 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) => ({
schema: (state as any).annoMatrix?.schema,
}))
class Continuous extends React.PureComponent {
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
.filter((col: any) => col.type === "int32" || col.type === "float32")
.filter((col: any) => col.name !== obsIndex)
.filter((col: any) => !col.writable) // skip user annotations - they will be treated as categorical
.map((col: any) => col.name);
return (
<div>
{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,7 +5,7 @@
******************************************/ ******************************************/
import * as d3 from "d3"; import * as d3 from "d3";
const setupParallelCoordinates = (width, height, margin) => { const setupParallelCoordinates = (width: any, height: any, margin: any) => {
const container = d3.select("#parcoords"); const container = d3.select("#parcoords");
const svg = container const svg = container
@@ -24,10 +24,15 @@ const setupParallelCoordinates = (width, height, margin) => {
.style("margin-top", `${margin.top}px`) .style("margin-top", `${margin.top}px`)
.style("margin-left", `${margin.left}px`); .style("margin-left", `${margin.left}px`);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const ctx = canvas.node().getContext("2d"); const ctx = canvas.node().getContext("2d");
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.globalCompositeOperation = "darken"; ctx.globalCompositeOperation = "darken";
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.globalAlpha = 0.15; ctx.globalAlpha = 0.15;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.lineWidth = 1.5; ctx.lineWidth = 1.5;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.scale(devicePixelRatio, devicePixelRatio); ctx.scale(devicePixelRatio, devicePixelRatio);
return { return {
@@ -12,14 +12,14 @@ export const innerHeight = height - 2;
export const devicePixelRatio = window.devicePixelRatio || 1; export const devicePixelRatio = window.devicePixelRatio || 1;
export const createDimensions = (data) => { export const createDimensions = (data: any) => {
const newArr = []; const newArr: any = [];
each(data, (value, key) => { each(data, (value, key) => {
if (value.range) { if (value.range) {
newArr.push({ newArr.push({
key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */, key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */,
type: { type: {
within: (d, extent, dim) => within: (d: any, extent: any, dim: any) =>
extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1], extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1],
}, },
scale: d3 scale: d3
@@ -32,16 +32,17 @@ export const createDimensions = (data) => {
return newArr; return newArr;
}; };
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
export const yAxis = d3.axisLeft(); export const yAxis = d3.axisLeft();
export const brushstart = () => { export const brushstart = () => {
d3.event.sourceEvent.stopPropagation(); (d3 as any).event.sourceEvent.stopPropagation();
}; };
// Unused. // Unused.
// export const d3_functor = v => (typeof v === "function" ? v : () => v); // export const d3_functor = v => (typeof v === "function" ? v : () => v);
export const project = (d, dimensions, xscale) => export const project = (d: any, dimensions: any, xscale: any) =>
dimensions.map((p, i) => { dimensions.map((p: any, i: any) => {
// check if data element has property and contains a value // check if data element has property and contains a value
if (!(p.key in d) || d[p.key] === null) return null; if (!(p.key in d) || d[p.key] === null) return null;
@@ -9,7 +9,7 @@ import {
} from "../../util/stateManager/colorHelpers"; } from "../../util/stateManager/colorHelpers";
// create continuous color legend // create continuous color legend
const continuous = (selectorId, colorScale, colorAccessor) => { const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => {
const legendHeight = 200; const legendHeight = 200;
const legendWidth = 80; const legendWidth = 80;
const margin = { top: 10, right: 60, bottom: 10, left: 2 }; const margin = { top: 10, right: 60, bottom: 10, left: 2 };
@@ -33,6 +33,7 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
we flip the color scale as well [1, 0] instead of [0, 1] */ we flip the color scale as well [1, 0] instead of [0, 1] */
.node(); .node();
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
const legendScale = d3 const legendScale = d3
@@ -44,6 +45,7 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
]); /* we flip this to make viridis colors dark if high in the color scale */ ]); /* 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 // 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); const image = ctx.createImageData(1, legendHeight);
d3.range(legendHeight).forEach((i) => { d3.range(legendHeight).forEach((i) => {
const c = d3.rgb(colorScale(legendScale.invert(i))); const c = d3.rgb(colorScale(legendScale.invert(i)));
@@ -52,6 +54,7 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
image.data[4 * i + 2] = c.b; image.data[4 * i + 2] = c.b;
image.data[4 * i + 3] = 255; image.data[4 * i + 3] = 255;
}); });
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
ctx.putImageData(image, 0, 0); ctx.putImageData(image, 0, 0);
// A simpler way to do the above, but possibly slower. keep in mind the legend // A simpler way to do the above, but possibly slower. keep in mind the legend
@@ -105,27 +108,26 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
.text(colorAccessor); .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) => ({ @connect((state) => ({
annoMatrix: state.annoMatrix, annoMatrix: (state as any).annoMatrix,
colors: state.colors, colors: (state as any).colors,
genesets: state.genesets.genesets, genesets: (state as any).genesets.genesets,
})) }))
class ContinuousLegend extends React.Component { class ContinuousLegend extends React.Component {
async componentDidUpdate(prevProps) { 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
const { annoMatrix, colors, genesets } = this.props; const { annoMatrix, colors, genesets } = this.props;
if (!colors || !annoMatrix) return; if (!colors || !annoMatrix) return;
if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) { if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) {
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorMode, colorAccessor, userColors } = colors; const { colorMode, colorAccessor, userColors } = colors;
const colorQuery = createColorQuery( const colorQuery = createColorQuery(
colorMode, colorMode,
colorAccessor, colorAccessor,
schema, schema,
genesets genesets
); );
const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null; const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null;
const colorTable = createColorTable( const colorTable = createColorTable(
colorMode, colorMode,
@@ -134,19 +136,19 @@ class ContinuousLegend extends React.Component {
schema, schema,
userColors userColors
); );
const colorScale = colorTable.scale; 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; 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]; const [domainMin, domainMax] = colorScale?.domain?.() ?? [0, 0];
/* always remove it, if it's not continuous we don't put it back. */ /* always remove it, if it's not continuous we don't put it back. */
d3.select("#continuous_legend").selectAll("*").remove(); d3.select("#continuous_legend").selectAll("*").remove();
if (colorAccessor && colorScale && range && domainMin < domainMax) { if (colorAccessor && colorScale && range && domainMin < domainMax) {
/* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */ /* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */
if (range()[0][0] !== "#") { if (range()[0][0] !== "#") {
continuous( continuous(
"#continuous_legend", "#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()), d3.scaleSequential(interpolateCool).domain(colorScale.domain()),
colorAccessor colorAccessor
); );
@@ -15,25 +15,30 @@ import * as globals from "../../globals";
import actions from "../../actions"; import actions from "../../actions";
import { getDiscreteCellEmbeddingRowIndex } from "../../util/stateManager/viewStackHelpers"; import { getDiscreteCellEmbeddingRowIndex } from "../../util/stateManager/viewStackHelpers";
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) => { @connect((state) => {
return { return {
layoutChoice: state.layoutChoice, // TODO: really should clean up naming, s/layout/embedding/g layoutChoice: (state as any).layoutChoice,
schema: state.annoMatrix?.schema, schema: (state as any).annoMatrix?.schema,
crossfilter: state.obsCrossfilter, crossfilter: (state as any).obsCrossfilter,
}; };
}) })
class Embedding extends React.PureComponent { class Embedding extends React.PureComponent<{}, EmbeddingState> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = {}; this.state = {};
} }
handleLayoutChoiceChange = (e) => { 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
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch(actions.layoutChoiceAction(e.currentTarget.value)); dispatch(actions.layoutChoiceAction(e.currentTarget.value));
}; };
render() { 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 { layoutChoice, schema, crossfilter } = this.props;
const { annoMatrix } = crossfilter; const { annoMatrix } = crossfilter;
return ( return (
@@ -100,10 +105,11 @@ class Embedding extends React.PureComponent {
export default Embedding; export default Embedding;
const loadAllEmbeddingCounts = async ({ annoMatrix, available }) => { const loadAllEmbeddingCounts = async ({ annoMatrix, available }: any) => {
const embeddings = await Promise.all( const embeddings = await Promise.all(
available.map((name) => annoMatrix.base().fetch("emb", name)) available.map((name: any) => annoMatrix.base().fetch("emb", name))
); );
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
return available.map((name, idx) => ({ return available.map((name, idx) => ({
embeddingName: name, embeddingName: name,
embedding: embeddings[idx], embedding: embeddings[idx],
@@ -111,7 +117,7 @@ const loadAllEmbeddingCounts = async ({ annoMatrix, available }) => {
})); }));
}; };
const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }) => { const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => {
const { available } = layoutChoice; const { available } = layoutChoice;
const { data, error, isPending } = useAsync({ const { data, error, isPending } = useAsync({
promiseFn: loadAllEmbeddingCounts, promiseFn: loadAllEmbeddingCounts,
@@ -127,7 +133,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }) => {
/* still loading, or errored out - just omit counts (TODO: spinner?) */ /* still loading, or errored out - just omit counts (TODO: spinner?) */
return ( return (
<RadioGroup onChange={onChange} selectedValue={layoutChoice.current}> <RadioGroup onChange={onChange} selectedValue={layoutChoice.current}>
{layoutChoice.available.map((name) => ( {layoutChoice.available.map((name: any) => (
<Radio label={`${name}`} value={name} key={name} /> <Radio label={`${name}`} value={name} key={name} />
))} ))}
</RadioGroup> </RadioGroup>
@@ -136,7 +142,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }) => {
if (data) { if (data) {
return ( return (
<RadioGroup onChange={onChange} selectedValue={layoutChoice.current}> <RadioGroup onChange={onChange} selectedValue={layoutChoice.current}>
{data.map((summary) => { {data.map((summary: any) => {
const { discreteCellIndex, embeddingName } = summary; const { discreteCellIndex, embeddingName } = summary;
const sizeHint = `${discreteCellIndex.size()} cells`; const sizeHint = `${discreteCellIndex.size()} cells`;
return ( return (
@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
function Container(props) { function Container(props: any) {
const { children } = props; const { children } = props;
return ( return (
<div <div
@@ -2,6 +2,7 @@ import React from "react";
import * as globals from "../../globals"; import * as globals from "../../globals";
class Layout extends React.Component { class Layout extends React.Component {
viewportRef: any;
/* /*
Layout - this react component contains all the layout style and logic for the application once it has loaded. Layout - this react component contains all the layout style and logic for the application once it has loaded.
@@ -23,6 +24,7 @@ class Layout extends React.Component {
render() { render() {
const { children } = this.props; 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; const [leftSidebar, renderGraph, rightSidebar] = children;
return ( return (
<div <div
@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import * as globals from "../../globals"; import * as globals from "../../globals";
const Logo = (props) => { const Logo = (props: any) => {
const { size } = props; const { size } = props;
return ( return (
<svg width={size} height={size} viewBox="0 0 48 48" fill="none"> <svg width={size} height={size} viewBox="0 0 48 48" fill="none">
@@ -11,20 +11,20 @@ const ToastTopCenter = Toaster.create({
/* /*
A "user" error - eg, bad input A "user" error - eg, bad input
*/ */
export const postUserErrorToast = (message) => export const postUserErrorToast = (message: any) =>
ToastTopCenter.show({ message, intent: Intent.WARNING }); ToastTopCenter.show({ message, intent: Intent.WARNING });
/* /*
A toast the user must dismiss manually, because they need to act on its information, 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. ie., 8 bulk add genes out of 40 were bad. Manually see which ones and fix.
*/ */
export const keepAroundErrorToast = (message) => export const keepAroundErrorToast = (message: any) =>
ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING }); ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING });
/* /*
a hard network error a hard network error
*/ */
export const postNetworkErrorToast = (message, key = undefined) => export const postNetworkErrorToast = (message: any, key = undefined) =>
ToastTopCenter.show( ToastTopCenter.show(
{ {
message, message,
@@ -37,14 +37,14 @@ export const postNetworkErrorToast = (message, key = undefined) =>
/* /*
Async message to user Async message to user
*/ */
export const postAsyncSuccessToast = (message) => export const postAsyncSuccessToast = (message: any) =>
ToastTopCenter.show({ ToastTopCenter.show({
message, message,
timeout: 10000, timeout: 10000,
intent: Intent.SUCCESS, intent: Intent.SUCCESS,
}); });
export const postAsyncFailureToast = (message) => export const postAsyncFailureToast = (message: any) =>
ToastTopCenter.show({ ToastTopCenter.show({
message, message,
timeout: 10000, timeout: 10000,
@@ -9,17 +9,23 @@ import actions from "../../actions";
const MINI_HISTOGRAM_WIDTH = 110; const MINI_HISTOGRAM_WIDTH = 110;
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) => { @connect((state, ownProps) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'gene' does not exist on type '{}'.
const { gene } = ownProps; const { gene } = ownProps;
return { return {
isColorAccessor: state.colors.colorAccessor === gene, isColorAccessor: (state as any).colors.colorAccessor === gene,
isScatterplotXXaccessor: state.controls.scatterplotXXaccessor === gene, isScatterplotXXaccessor:
isScatterplotYYaccessor: state.controls.scatterplotYYaccessor === gene, (state as any).controls.scatterplotXXaccessor === gene,
isScatterplotYYaccessor:
(state as any).controls.scatterplotYYaccessor === gene,
}; };
}) })
class Gene extends React.Component { class Gene extends React.Component<{}, State> {
constructor(props) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
geneIsExpanded: false, geneIsExpanded: false,
@@ -27,6 +33,7 @@ class Gene extends React.Component {
} }
onColorChangeClick = () => { 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; const { dispatch, gene } = this.props;
dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(gene)); dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(gene));
}; };
@@ -37,6 +44,7 @@ class Gene extends React.Component {
}; };
handleSetGeneAsScatterplotX = () => { 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; const { dispatch, gene } = this.props;
dispatch({ dispatch({
type: "set scatterplot x", type: "set scatterplot x",
@@ -45,6 +53,7 @@ class Gene extends React.Component {
}; };
handleSetGeneAsScatterplotY = () => { 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; const { dispatch, gene } = this.props;
dispatch({ dispatch({
type: "set scatterplot y", type: "set scatterplot y",
@@ -53,18 +62,26 @@ class Gene extends React.Component {
}; };
handleDeleteGeneFromSet = () => { 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; const { dispatch, gene, geneset } = this.props;
dispatch(actions.genesetDeleteGenes(geneset, [gene])); dispatch(actions.genesetDeleteGenes(geneset, [gene]));
}; };
render() { render() {
const { 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, 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, 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, isColorAccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotXXaccessor, isScatterplotXXaccessor,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message
isScatterplotYYaccessor, 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, 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, removeGene,
} = this.props; } = this.props;
const { geneIsExpanded } = this.state; const { geneIsExpanded } = this.state;
@@ -84,6 +101,7 @@ class Gene extends React.Component {
> >
<div <div
role="menuitem" 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" tabIndex="0"
data-testclass="gene-expand" data-testclass="gene-expand"
data-testid={`${gene}:gene-expand`} data-testid={`${gene}:gene-expand`}
@@ -124,6 +142,7 @@ class Gene extends React.Component {
</div> </div>
{!geneIsExpanded ? ( {!geneIsExpanded ? (
<HistogramBrush <HistogramBrush
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
isUserDefined isUserDefined
field={gene} field={gene}
mini mini
@@ -188,6 +207,7 @@ class Gene extends React.Component {
/> />
</div> </div>
</div> </div>
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
{geneIsExpanded && <HistogramBrush isUserDefined field={gene} />} {geneIsExpanded && <HistogramBrush isUserDefined field={gene} />}
</div> </div>
); );

Some files were not shown because too many files have changed in this diff Show More