diff --git a/backend/test/fixtures/pbmc3k-genesets.csv b/backend/test/fixtures/pbmc3k-genesets.csv index ebd079de..ea624c68 100644 --- a/backend/test/fixtures/pbmc3k-genesets.csv +++ b/backend/test/fixtures/pbmc3k-genesets.csv @@ -18,4 +18,4 @@ geneset_to_delete,,, geneset_to_edit,,, fill_this_geneset,,, empty_this_geneset,,SIK1, -brush_this_gene,,SIK1, \ No newline at end of file +brush_this_gene,,SIK1, diff --git a/client/__tests__/e2e/__snapshots__/e2e.test.ts.snap b/client/__tests__/e2e/__snapshots__/e2e.test.js.snap similarity index 100% rename from client/__tests__/e2e/__snapshots__/e2e.test.ts.snap rename to client/__tests__/e2e/__snapshots__/e2e.test.js.snap diff --git a/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.ts.snap b/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap similarity index 100% rename from client/__tests__/e2e/__snapshots__/e2eAnnotations.test.ts.snap rename to client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap diff --git a/client/__tests__/e2e/cellxgeneActions.js b/client/__tests__/e2e/cellxgeneActions.js new file mode 100644 index 00000000..81727712 --- /dev/null +++ b/client/__tests__/e2e/cellxgeneActions.js @@ -0,0 +1,506 @@ +/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ +import { strict as assert } from "assert"; +import { + clearInputAndTypeInto, + clickOn, + getAllByClass, + getOneElementInnerText, + typeInto, + waitByID, + waitByClass, + waitForAllByIds, + clickOnUntil, + getTestClass, + getTestId, + isElementPresent, + goToPage, +} from "./puppeteerUtils"; + +import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config"; + +export async function drag(testId, start, end, lasso = false) { + const layout = await waitByID(testId); + const elBox = await layout.boxModel(); + const x1 = elBox.content[0].x + start.x; + const x2 = elBox.content[0].x + end.x; + const y1 = elBox.content[0].y + start.y; + const y2 = elBox.content[0].y + end.y; + await page.mouse.move(x1, y1); + await page.mouse.down(); + if (lasso) { + await page.mouse.move(x2, y1); + await page.mouse.move(x2, y2); + await page.mouse.move(x1, y2); + await page.mouse.move(x1, y1); + } else { + await page.mouse.move(x2, y2); + } + await page.mouse.up(); +} + +export async function clickOnCoordinate(testId, coord) { + const layout = await expect(page).toMatchElement(getTestId(testId)); + const elBox = await layout.boxModel(); + + if (!elBox) { + throw Error("Layout's boxModel is not available!"); + } + + const x = elBox.content[0].x + coord.x; + const y = elBox.content[0].y + coord.y; + await page.mouse.click(x, y); +} + +export async function getAllHistograms(testclass, testIds) { + const histTestIds = testIds.map((tid) => `histogram-${tid}`); + + // these load asynchronously, so we need to wait for each histogram individually, + // and they may be quite slow in some cases. + await waitForAllByIds(histTestIds, { timeout: 4 * 60 * 1000 }); + + const allHistograms = await getAllByClass(testclass); + + const testIDs = await Promise.all( + allHistograms.map((hist) => page.evaluate((elem) => elem.dataset.testid, hist)) + ); + + return testIDs.map((id) => id.replace(/^histogram-/, "")); +} + +export async function getAllCategoriesAndCounts(category) { + // these load asynchronously, so we have to wait for the specific category. + await waitByID(`category-${category}`); + + return page.$$eval( + `[data-testid="category-${category}"] [data-testclass='categorical-row']`, + (rows) => + Object.fromEntries( + rows.map((row) => { + const cat = row + .querySelector("[data-testclass='categorical-value']") + .getAttribute("aria-label"); + + const count = row.querySelector( + "[data-testclass='categorical-value-count']" + ).innerText; + + return [cat, count]; + }) + ) + ); +} + +export async function getCellSetCount(num) { + await clickOn(`cellset-button-${num}`); + return getOneElementInnerText(`[data-testid='cellset-count-${num}']`); +} + +export async function resetCategory(category) { + const checkboxId = `${category}:category-select`; + await waitByID(checkboxId); + const checkedPseudoclass = await page.$eval( + `[data-testid='${checkboxId}']`, + (el) => el.matches(":checked") + ); + if (!checkedPseudoclass) await clickOn(checkboxId); + + const categoryRow = await waitByID(`${category}:category-expand`); + + const isExpanded = await categoryRow.$( + "[data-testclass='category-expand-is-expanded']" + ); + + if (isExpanded) await clickOn(`${category}:category-expand`); +} + +export async function calcCoordinate(testId, xAsPercent, yAsPercent) { + const el = await waitByID(testId); + const size = await el.boxModel(); + return { + x: Math.floor(size.width * xAsPercent), + y: Math.floor(size.height * yAsPercent), + }; +} + +export async function calcDragCoordinates(testId, coordinateAsPercent) { + return { + start: await calcCoordinate( + testId, + coordinateAsPercent.x1, + coordinateAsPercent.y1 + ), + end: await calcCoordinate( + testId, + coordinateAsPercent.x2, + coordinateAsPercent.y2 + ), + }; +} + +export async function selectCategory(category, values, reset = true) { + if (reset) await resetCategory(category); + + await clickOn(`${category}:category-expand`); + await clickOn(`${category}:category-select`); + + for (const value of values) { + await clickOn(`categorical-value-select-${category}-${value}`); + } +} + +export async function expandCategory(category) { + const expand = await waitByID(`${category}:category-expand`); + const notExpanded = await expand.$( + "[data-testclass='category-expand-is-not-expanded']" + ); + if (notExpanded) await clickOn(`${category}:category-expand`); +} + +export async function clip(min = 0, max = 100) { + await clickOn("visualization-settings"); + await clearInputAndTypeInto("clip-min-input", min); + await clearInputAndTypeInto("clip-max-input", max); + await clickOn("clip-commit"); +} + +export async function createCategory(categoryName) { + await clickOnUntil("open-annotation-dialog", async () => { + await expect(page).toMatchElement(getTestId("new-category-name")); + }); + + await typeInto("new-category-name", categoryName); + await clickOn("submit-category"); +} + +/* + + GENESET + +*/ + +export async function colorByGeneset(genesetName) { + await clickOn(`${genesetName}:colorby-entire-geneset`); +} + +export async function colorByGene(gene) { + await clickOn(`colorby-${gene}`); +} + +export async function assertColorLegendLabel(label) { + const handle = await waitByID("continuous_legend_color_by_label"); + + const result = await handle.evaluate((node) => node.getAttribute("aria-label")); + + return expect(result).toBe(label); +} + +export async function expandGeneset(genesetName) { + const expand = await waitByID(`${genesetName}:geneset-expand`); + const notExpanded = await expand.$( + "[data-testclass='geneset-expand-is-not-expanded']" + ); + if (notExpanded) await clickOn(`${genesetName}:geneset-expand`); +} + +export async function createGeneset(genesetName) { + await clickOnUntil("open-create-geneset-dialog", async () => { + await expect(page).toMatchElement(getTestId("create-geneset-input")); + }); + + await typeInto("create-geneset-input", genesetName); + await clickOn("submit-geneset"); + await waitByClass("autosave-complete"); +} + +export async function editGenesetName(genesetName, editText) { + const editButton = `${genesetName}:edit-genesetName-mode`; + const submitButton = `${genesetName}:submit-geneset`; + await clickOnUntil(`${genesetName}:see-actions`, async () => { + await expect(page).toMatchElement(getTestId(editButton)); + }); + await clickOn(editButton); + await typeInto("rename-geneset-modal", editText); + await clickOn(submitButton); +} + +export async function deleteGeneset(genesetName) { + const targetId = `${genesetName}:delete-geneset`; + + await clickOnUntil(`${genesetName}:see-actions`, async () => { + await expect(page).toMatchElement(getTestId(targetId)); + }); + + await clickOn(targetId); + + await assertGenesetDoesNotExist(genesetName); + await waitByClass("autosave-complete"); +} + +export async function assertGenesetDoesNotExist(genesetName) { + const result = await isElementPresent( + getTestId(`${genesetName}:geneset-name`) + ); + await expect(result).toBe(false); +} + +export async function assertGenesetExists(genesetName) { + const handle = await waitByID(`${genesetName}:geneset-name`); + + const result = await handle.evaluate((node) => node.getAttribute("aria-label")); + + return expect(result).toBe(genesetName); +} + +/* + + GENE + +*/ + +export async function addGeneToSet(genesetName, geneToAddToSet) { + const submitButton = `${genesetName}:submit-gene`; + + await clickOn(`${genesetName}:add-new-gene-to-geneset`); + await typeInto("add-genes", geneToAddToSet); + await clickOn(submitButton); +} + +export async function removeGene(geneSymbol) { + const targetId = `delete-from-geneset:${geneSymbol}`; + + await clickOn(targetId); + + await waitByClass("autosave-complete"); +} + +export async function assertGeneExistsInGeneset(geneSymbol) { + const handle = await waitByID(`${geneSymbol}:gene-label`); + + const result = await handle.evaluate((node) => node.getAttribute("aria-label")); + + return expect(result).toBe(geneSymbol); +} + +export async function assertGeneDoesNotExist(geneSymbol) { + const result = await isElementPresent(getTestId(`${geneSymbol}:gene-label`)); + + await expect(result).toBe(false); +} + +export async function expandGene(geneSymbol) { + await clickOn(`maximize-${geneSymbol}`); +} + +/* + + CATEGORY + +*/ + +export async function duplicateCategory(categoryName) { + await clickOn("open-annotation-dialog"); + + await typeInto("new-category-name", categoryName); + + const dropdownOptionClass = "duplicate-category-dropdown-option"; + + await clickOnUntil("duplicate-category-dropdown", async () => { + await expect(page).toMatchElement(getTestClass(dropdownOptionClass)); + }); + + const option = await expect(page).toMatchElement( + getTestClass(dropdownOptionClass) + ); + + await option.click(); + + await clickOnUntil("submit-category", async () => { + await expect(page).toMatchElement( + getTestId(`${categoryName}:category-expand`) + ); + }); + + await waitByClass("autosave-complete"); +} + +export async function renameCategory(oldCategoryName, newCategoryName) { + await clickOn(`${oldCategoryName}:see-actions`); + await clickOn(`${oldCategoryName}:edit-category-mode`); + await clearInputAndTypeInto( + `${oldCategoryName}:edit-category-name-text`, + newCategoryName + ); + await clickOn(`${oldCategoryName}:submit-category-edit`); +} + +export async function deleteCategory(categoryName) { + const targetId = `${categoryName}:delete-category`; + + await clickOnUntil(`${categoryName}:see-actions`, async () => { + await expect(page).toMatchElement(getTestId(targetId)); + }); + + await clickOn(targetId); + + await assertCategoryDoesNotExist(); +} + +export async function createLabel(categoryName, labelName) { + /** + * (thuang): This explicit wait is needed, since currently showing + * the modal again quickly after the previous action dismissing the + * modal will persist the input value from the previous action. + * + * To reproduce: + * 1. Click on the plus sign to show the modal to add a new label to the category + * 2. Type `123` in the input box + * 3. Hover over your mouse over the plus sign and double click to quickly dismiss and + * invoke the modal again + * 4. You will see `123` is persisted in the input box + * 5. Expected behavior is to get an empty input box + */ + await page.waitForTimeout(500); + + await clickOn(`${categoryName}:see-actions`); + + await clickOn(`${categoryName}:add-new-label-to-category`); + + await typeInto(`${categoryName}:new-label-name`, labelName); + + await clickOn(`${categoryName}:submit-label`); +} + +export async function deleteLabel(categoryName, labelName) { + await expandCategory(categoryName); + await clickOn(`${categoryName}:${labelName}:see-actions`); + await clickOn(`${categoryName}:${labelName}:delete-label`); +} + +export async function renameLabel(categoryName, oldLabelName, newLabelName) { + await expandCategory(categoryName); + await clickOn(`${categoryName}:${oldLabelName}:see-actions`); + await clickOn(`${categoryName}:${oldLabelName}:edit-label`); + await clearInputAndTypeInto( + `${categoryName}:${oldLabelName}:edit-label-name`, + newLabelName + ); + await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`); +} + +export async function addGeneToSearch(geneName) { + await typeInto("gene-search", geneName); + await page.keyboard.press("Enter"); + await page.waitForSelector(`[data-testid='histogram-${geneName}']`); +} + +export async function subset(coordinatesAsPercent) { + // In order to deselect the selection after the subset, make sure we have some clear part + // of the scatterplot we can click on + assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99); + const lassoSelection = await calcDragCoordinates( + "layout-graph", + coordinatesAsPercent + ); + await drag("layout-graph", lassoSelection.start, lassoSelection.end, true); + await clickOn("subset-button"); + const clearCoordinate = await calcCoordinate("layout-graph", 0.5, 0.99); + await clickOnCoordinate("layout-graph", clearCoordinate); +} + +export async function setSellSet(cellSet, cellSetNum) { + const selections = cellSet.filter((sel) => sel.kind === "categorical"); + + for (const selection of selections) { + await selectCategory(selection.metadata, selection.values, true); + } + + await getCellSetCount(cellSetNum); +} + +export async function runDiffExp(cellSet1, cellSet2) { + await setSellSet(cellSet1, 1); + await setSellSet(cellSet2, 2); + await clickOn("diffexp-button"); +} + +export async function bulkAddGenes(geneNames) { + await clickOn("section-bulk-add"); + await typeInto("input-bulk-add", geneNames.join(",")); + await page.keyboard.press("Enter"); +} + +export async function assertCategoryDoesNotExist(categoryName) { + const result = await isElementPresent( + getTestId(`${categoryName}:category-label`) + ); + + await expect(result).toBe(false); +} + +export async function login() { + await goToPage(appUrlBase); + + await clickOn("log-in"); + + // (thuang): Auth0 form is unstable and unsafe for input until verified + await waitUntilFormFieldStable('[name="email"]'); + + await expect(page).toFillForm("form", { + email: TEST_EMAIL, + password: TEST_PASSWORD, + }); + + await Promise.all([ + page.waitForNavigation({ waitUntil: "networkidle0" }), + expect(page).toClick('[name="submit"]'), + ]); + + expect(page.url()).toContain(appUrlBase); +} + +export async function logout() { + await clickOnUntil("user-info", async () => { + await waitByID("log-out"); + await Promise.all([ + page.waitForNavigation({ waitUntil: "networkidle0" }), + clickOn("log-out"), + ]); + }); + + await waitByID("log-in"); +} + +async function waitUntilFormFieldStable(selector) { + const MAX_RETRY = 10; + const WAIT_FOR_MS = 200; + + const EXPECTED_VALUE = "aaa"; + + let retry = 0; + + while (retry < MAX_RETRY) { + try { + await expect(page).toFill(selector, EXPECTED_VALUE); + + const fieldHandle = await expect(page).toMatchElement(selector); + + const fieldValue = await page.evaluate( + (input) => input.value, + fieldHandle + ); + + expect(fieldValue).toBe(EXPECTED_VALUE); + + break; + } catch (error) { + retry += 1; + + await page.waitForTimeout(WAIT_FOR_MS); + } + } + + if (retry === MAX_RETRY) { + throw Error("clickOnUntil() assertion failed!"); + } +} +/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/cellxgeneActions.ts b/client/__tests__/e2e/cellxgeneActions.ts deleted file mode 100644 index 5a3333dd..00000000 --- a/client/__tests__/e2e/cellxgeneActions.ts +++ /dev/null @@ -1,597 +0,0 @@ -/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ -import { strict as assert } from "assert"; -import { - clearInputAndTypeInto, - clickOn, - getAllByClass, - getOneElementInnerText, - typeInto, - waitByID, - waitByClass, - waitForAllByIds, - clickOnUntil, - getTestClass, - getTestId, - isElementPresent, - goToPage, -} from "./puppeteerUtils"; - -import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config"; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function drag(testId: any, start: any, end: any, lasso = false) { - const layout = await waitByID(testId); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const elBox = await layout.boxModel(); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - 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; - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - 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; - await page.mouse.move(x1, y1); - await page.mouse.down(); - if (lasso) { - await page.mouse.move(x2, y1); - await page.mouse.move(x2, y2); - await page.mouse.move(x1, y2); - await page.mouse.move(x1, y1); - } else { - await page.mouse.move(x2, y2); - } - await page.mouse.up(); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function clickOnCoordinate(testId: any, coord: any) { - const layout = await expect(page).toMatchElement(getTestId(testId)); - const elBox = await layout.boxModel(); - - if (!elBox) { - throw Error("Layout's boxModel is not available!"); - } - - const x = elBox.content[0].x + coord.x; - const y = elBox.content[0].y + coord.y; - await page.mouse.click(x, y); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getAllHistograms(testclass: any, testIds: any) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const histTestIds = testIds.map((tid: any) => `histogram-${tid}`); - - // these load asynchronously, so we need to wait for each histogram individually, - // 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 }); - - const allHistograms = await getAllByClass(testclass); - - const testIDs = await Promise.all( - allHistograms.map((hist) => - page.evaluate((elem) => elem.dataset.testid, hist) - ) - ); - - return testIDs.map((id) => id.replace(/^histogram-/, "")); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getAllCategoriesAndCounts(category: any) { - // these load asynchronously, so we have to wait for the specific category. - await waitByID(`category-${category}`); - - return page.$$eval( - `[data-testid="category-${category}"] [data-testclass='categorical-row']`, - (rows) => - Object.fromEntries( - rows.map((row) => { - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const cat = row - .querySelector("[data-testclass='categorical-value']") - .getAttribute("aria-label"); - - const count = ( - row.querySelector( - "[data-testclass='categorical-value-count']" - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - ) as any - ).innerText; - - return [cat, count]; - }) - ) - ); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getCellSetCount(num: any) { - await clickOn(`cellset-button-${num}`); - return getOneElementInnerText(`[data-testid='cellset-count-${num}']`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function resetCategory(category: any) { - const checkboxId = `${category}:category-select`; - await waitByID(checkboxId); - const checkedPseudoclass = await page.$eval( - `[data-testid='${checkboxId}']`, - (el) => el.matches(":checked") - ); - if (!checkedPseudoclass) await clickOn(checkboxId); - - const categoryRow = await waitByID(`${category}:category-expand`); - - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const isExpanded = await categoryRow.$( - "[data-testclass='category-expand-is-expanded']" - ); - - if (isExpanded) await clickOn(`${category}:category-expand`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function calcCoordinate( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - testId: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - xAsPercent: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - yAsPercent: any -) { - const el = await waitByID(testId); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const size = await el.boxModel(); - return { - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - x: Math.floor(size.width * xAsPercent), - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - y: Math.floor(size.height * yAsPercent), - }; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function calcDragCoordinates( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - testId: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - coordinateAsPercent: any -) { - return { - start: await calcCoordinate( - testId, - coordinateAsPercent.x1, - coordinateAsPercent.y1 - ), - end: await calcCoordinate( - testId, - coordinateAsPercent.x2, - coordinateAsPercent.y2 - ), - }; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function selectCategory(category: any, values: any, reset = true) { - if (reset) await resetCategory(category); - - await clickOn(`${category}:category-expand`); - await clickOn(`${category}:category-select`); - - for (const value of values) { - await clickOn(`categorical-value-select-${category}-${value}`); - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function expandCategory(category: any) { - const expand = await waitByID(`${category}:category-expand`); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const notExpanded = await expand.$( - "[data-testclass='category-expand-is-not-expanded']" - ); - if (notExpanded) await clickOn(`${category}:category-expand`); -} - -export async function clip(min = "0", max = "100"): Promise { - await clickOn("visualization-settings"); - await clearInputAndTypeInto("clip-min-input", min); - await clearInputAndTypeInto("clip-max-input", max); - await clickOn("clip-commit"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function createCategory(categoryName: any) { - await clickOnUntil("open-annotation-dialog", async () => { - await expect(page).toMatchElement(getTestId("new-category-name")); - }); - - await typeInto("new-category-name", categoryName); - await clickOn("submit-category"); -} - -/** - * GENESET - */ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function colorByGeneset(genesetName: any) { - await clickOn(`${genesetName}:colorby-entire-geneset`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function colorByGene(gene: any) { - await clickOn(`colorby-${gene}`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function assertColorLegendLabel(label: any) { - 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) => - node.getAttribute("aria-label") - ); - - return expect(result).toBe(label); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function expandGeneset(genesetName: any) { - const expand = await waitByID(`${genesetName}:geneset-expand`); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const notExpanded = await expand.$( - "[data-testclass='geneset-expand-is-not-expanded']" - ); - if (notExpanded) await clickOn(`${genesetName}:geneset-expand`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function createGeneset(genesetName: any) { - await clickOnUntil("open-create-geneset-dialog", async () => { - await expect(page).toMatchElement(getTestId("create-geneset-input")); - }); - - await typeInto("create-geneset-input", genesetName); - await clickOn("submit-geneset"); - await waitByClass("autosave-complete"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function editGenesetName(genesetName: any, editText: any) { - const editButton = `${genesetName}:edit-genesetName-mode`; - const submitButton = `${genesetName}:submit-geneset`; - await clickOnUntil(`${genesetName}:see-actions`, async () => { - await expect(page).toMatchElement(getTestId(editButton)); - }); - await clickOn(editButton); - await typeInto("rename-geneset-modal", editText); - await clickOn(submitButton); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function deleteGeneset(genesetName: any) { - const targetId = `${genesetName}:delete-geneset`; - - await clickOnUntil(`${genesetName}:see-actions`, async () => { - await expect(page).toMatchElement(getTestId(targetId)); - }); - - await clickOn(targetId); - - await assertGenesetDoesNotExist(genesetName); - await waitByClass("autosave-complete"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function assertGenesetDoesNotExist(genesetName: any) { - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - const result = await isElementPresent( - getTestId(`${genesetName}:geneset-name`) - ); - await expect(result).toBe(false); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function assertGenesetExists(genesetName: any) { - const handle = await waitByID(`${genesetName}:geneset-name`); - - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const result = await handle.evaluate((node) => - node.getAttribute("aria-label") - ); - - return expect(result).toBe(genesetName); -} - -/** - * GENE - */ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function addGeneToSet(genesetName: any, geneToAddToSet: any) { - const submitButton = `${genesetName}:submit-gene`; - - await clickOn(`${genesetName}:add-new-gene-to-geneset`); - await typeInto("add-genes", geneToAddToSet); - await clickOn(submitButton); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function removeGene(geneSymbol: any) { - const targetId = `delete-from-geneset:${geneSymbol}`; - - await clickOn(targetId); - - await waitByClass("autosave-complete"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function assertGeneExistsInGeneset(geneSymbol: any) { - const handle = await waitByID(`${geneSymbol}:gene-label`); - - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - const result = await handle.evaluate((node) => - node.getAttribute("aria-label") - ); - - return expect(result).toBe(geneSymbol); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -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`)); - - await expect(result).toBe(false); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function expandGene(geneSymbol: any) { - await clickOn(`maximize-${geneSymbol}`); -} - -/** - * CATEGORY - */ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function duplicateCategory(categoryName: any) { - await clickOn("open-annotation-dialog"); - - await typeInto("new-category-name", categoryName); - - const dropdownOptionClass = "duplicate-category-dropdown-option"; - - await clickOnUntil("duplicate-category-dropdown", async () => { - await expect(page).toMatchElement(getTestClass(dropdownOptionClass)); - }); - - const option = await expect(page).toMatchElement( - getTestClass(dropdownOptionClass) - ); - - await option.click(); - - await clickOnUntil("submit-category", async () => { - await expect(page).toMatchElement( - getTestId(`${categoryName}:category-expand`) - ); - }); - - await waitByClass("autosave-complete"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function renameCategory( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - oldCategoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - newCategoryName: any -) { - await clickOn(`${oldCategoryName}:see-actions`); - await clickOn(`${oldCategoryName}:edit-category-mode`); - await clearInputAndTypeInto( - `${oldCategoryName}:edit-category-name-text`, - newCategoryName - ); - await clickOn(`${oldCategoryName}:submit-category-edit`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function deleteCategory(categoryName: any) { - const targetId = `${categoryName}:delete-category`; - - await clickOnUntil(`${categoryName}:see-actions`, async () => { - await expect(page).toMatchElement(getTestId(targetId)); - }); - - await clickOn(targetId); - - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. - await assertCategoryDoesNotExist(); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function createLabel(categoryName: any, labelName: any) { - /** - * (thuang): This explicit wait is needed, since currently showing - * the modal again quickly after the previous action dismissing the - * modal will persist the input value from the previous action. - * - * To reproduce: - * 1. Click on the plus sign to show the modal to add a new label to the category - * 2. Type `123` in the input box - * 3. Hover over your mouse over the plus sign and double click to quickly dismiss and - * invoke the modal again - * 4. You will see `123` is persisted in the input box - * 5. Expected behavior is to get an empty input box - */ - await page.waitForTimeout(500); - - await clickOn(`${categoryName}:see-actions`); - - await clickOn(`${categoryName}:add-new-label-to-category`); - - await typeInto(`${categoryName}:new-label-name`, labelName); - - await clickOn(`${categoryName}:submit-label`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function deleteLabel(categoryName: any, labelName: any) { - await expandCategory(categoryName); - await clickOn(`${categoryName}:${labelName}:see-actions`); - await clickOn(`${categoryName}:${labelName}:delete-label`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function renameLabel( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - oldLabelName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - newLabelName: any -) { - await expandCategory(categoryName); - await clickOn(`${categoryName}:${oldLabelName}:see-actions`); - await clickOn(`${categoryName}:${oldLabelName}:edit-label`); - await clearInputAndTypeInto( - `${categoryName}:${oldLabelName}:edit-label-name`, - newLabelName - ); - await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function addGeneToSearch(geneName: any) { - await typeInto("gene-search", geneName); - await page.keyboard.press("Enter"); - await page.waitForSelector(`[data-testid='histogram-${geneName}']`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function subset(coordinatesAsPercent: any) { - // In order to deselect the selection after the subset, make sure we have some clear part - // of the scatterplot we can click on - assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99); - const lassoSelection = await calcDragCoordinates( - "layout-graph", - coordinatesAsPercent - ); - await drag("layout-graph", lassoSelection.start, lassoSelection.end, true); - await clickOn("subset-button"); - const clearCoordinate = await calcCoordinate("layout-graph", 0.5, 0.99); - await clickOnCoordinate("layout-graph", clearCoordinate); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function setSellSet(cellSet: any, cellSetNum: any) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const selections = cellSet.filter((sel: any) => sel.kind === "categorical"); - - for (const selection of selections) { - await selectCategory(selection.metadata, selection.values, true); - } - - await getCellSetCount(cellSetNum); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function runDiffExp(cellSet1: any, cellSet2: any) { - await setSellSet(cellSet1, 1); - await setSellSet(cellSet2, 2); - await clickOn("diffexp-button"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function bulkAddGenes(geneNames: any) { - await clickOn("section-bulk-add"); - await typeInto("input-bulk-add", geneNames.join(",")); - await page.keyboard.press("Enter"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function assertCategoryDoesNotExist(categoryName: any) { - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - const result = await isElementPresent( - getTestId(`${categoryName}:category-label`) - ); - - await expect(result).toBe(false); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function login() { - await goToPage(appUrlBase); - - await clickOn("log-in"); - - // (thuang): Auth0 form is unstable and unsafe for input until verified - await waitUntilFormFieldStable('[name="email"]'); - - await expect(page).toFillForm("form", { - email: TEST_EMAIL, - password: TEST_PASSWORD, - }); - - await Promise.all([ - page.waitForNavigation({ waitUntil: "networkidle0" }), - expect(page).toClick('[name="submit"]'), - ]); - - expect(page.url()).toContain(appUrlBase); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function logout() { - await clickOnUntil("user-info", async () => { - await waitByID("log-out"); - await Promise.all([ - page.waitForNavigation({ waitUntil: "networkidle0" }), - clickOn("log-out"), - ]); - }); - - await waitByID("log-in"); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -async function waitUntilFormFieldStable(selector: any) { - const MAX_RETRY = 10; - const WAIT_FOR_MS = 200; - - const EXPECTED_VALUE = "aaa"; - - let retry = 0; - - while (retry < MAX_RETRY) { - try { - await expect(page).toFill(selector, EXPECTED_VALUE); - - const fieldHandle = await expect(page).toMatchElement(selector); - - const fieldValue = await page.evaluate( - (input) => input.value, - fieldHandle - ); - - expect(fieldValue).toBe(EXPECTED_VALUE); - - break; - } catch (error) { - retry += 1; - - await page.waitForTimeout(WAIT_FOR_MS); - } - } - - if (retry === MAX_RETRY) { - throw Error("clickOnUntil() assertion failed!"); - } -} -/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/config.ts b/client/__tests__/e2e/config.js similarity index 100% rename from client/__tests__/e2e/config.ts rename to client/__tests__/e2e/config.js diff --git a/client/__tests__/e2e/data.ts b/client/__tests__/e2e/data.js similarity index 100% rename from client/__tests__/e2e/data.ts rename to client/__tests__/e2e/data.js diff --git a/client/__tests__/e2e/diffexpGeneSets.ts b/client/__tests__/e2e/diffexpGeneSets.js similarity index 100% rename from client/__tests__/e2e/diffexpGeneSets.ts rename to client/__tests__/e2e/diffexpGeneSets.js diff --git a/client/__tests__/e2e/e2e.test.ts b/client/__tests__/e2e/e2e.test.js similarity index 91% rename from client/__tests__/e2e/e2e.test.ts rename to client/__tests__/e2e/e2e.test.js index 2c9ad2ed..bd3e852a 100644 --- a/client/__tests__/e2e/e2e.test.ts +++ b/client/__tests__/e2e/e2e.test.js @@ -58,12 +58,10 @@ describe("metadata loads", () => { const categories = await getAllCategoriesAndCounts(label); 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]) ); 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]) ); } @@ -161,12 +159,10 @@ describe("subset", () => { const categories = await getAllCategoriesAndCounts(label); 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]) ); 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]) ); } @@ -258,7 +254,6 @@ describe("centroid labels", () => { const generatedLabels = await getAllByClass("centroid-label"); // Number of labels generated should be equal to size of the object 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 ); } @@ -280,7 +275,6 @@ describe("graph overlay", () => { 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 initialCoordinates = await getElementCoordinates( `${categoryValue}-centroid-label` diff --git a/client/__tests__/e2e/e2eAnnotations.test.ts b/client/__tests__/e2e/e2eAnnotations.test.js similarity index 89% rename from client/__tests__/e2e/e2eAnnotations.test.ts rename to client/__tests__/e2e/e2eAnnotations.test.js index 470a36ba..f42a6ff4 100644 --- a/client/__tests__/e2e/e2eAnnotations.test.ts +++ b/client/__tests__/e2e/e2eAnnotations.test.js @@ -82,8 +82,7 @@ const genesetDescriptionID = const genesetDescriptionString = "fourth_gene_set: fourth description"; const genesetToCheckForDescription = "fourth_gene_set"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -async function setup(config: any) { +async function setup(config) { await goToPage(appUrlBase); if (config.categoricalAnno) { @@ -157,8 +156,7 @@ describe.each([ await expect(page).toClick(getTestClass("pop-1-geneset-expand")); await page.waitForFunction( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (selector: any) => !document.querySelector(selector), + (selector) => !document.querySelector(selector), {}, getTestClass("gene-loading-spinner") ); @@ -173,8 +171,7 @@ describe.each([ await expect(page).toClick(getTestClass("pop-2-geneset-expand")); await page.waitForFunction( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (selector: any) => !document.querySelector(selector), + (selector) => !document.querySelector(selector), {}, getTestClass("gene-loading-spinner") ); @@ -405,13 +402,8 @@ describe.each([ expect(actualLabelName).toBe(expectedLabelName); expect(actualLabelCount).toBe(expectedLabelCount); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - async function getInnerText(element: any, className: any) { - return element.$eval( - getTestClass(className), - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (node: any) => node?.innerText - ); + async function getInnerText(element, className) { + return element.$eval(getTestClass(className), (node) => node?.innerText); } }); @@ -436,9 +428,7 @@ describe.each([ `categorical-value-count-${perTestCategoryName}-${perTestLabelName}` ); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. 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] ); }); @@ -498,7 +488,6 @@ describe.each([ await createLabel(perTestCategoryName, labelName); await assertLabelExists(perTestCategoryName, labelName); await clickOn("undo"); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. await assertLabelDoesNotExist(perTestCategoryName); await clickOn("redo"); await assertLabelExists(perTestCategoryName, labelName); @@ -508,12 +497,10 @@ describe.each([ await setup(config); await deleteLabel(perTestCategoryName, perTestLabelName); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. await assertLabelDoesNotExist(perTestCategoryName); await clickOn("undo"); await assertLabelExists(perTestCategoryName, perTestLabelName); await clickOn("redo"); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. await assertLabelDoesNotExist(perTestCategoryName); }); @@ -544,9 +531,7 @@ describe.each([ const labels = await getAllByClass("categorical-row"); const result = await Promise.all( - labels.map((label) => - page.evaluate((element) => element.outerHTML, label) - ) + labels.map((label) => page.evaluate((element) => element.outerHTML, label)) ); expect(result).toMatchSnapshot(); @@ -574,11 +559,9 @@ describe.each([ expect(result).toMatchSnapshot(); }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - async function assertCategoryExists(categoryName: any) { + async function assertCategoryExists(categoryName) { const handle = await waitByID(`${categoryName}:category-label`); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. const result = await handle.evaluate((node) => node.getAttribute("aria-label") ); @@ -586,8 +569,7 @@ describe.each([ return expect(result).toBe(categoryName); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - async function assertLabelExists(categoryName: any, labelName: any) { + async function assertLabelExists(categoryName, labelName) { await expect(page).toMatchElement( getTestId(`${categoryName}:category-expand`) ); @@ -599,13 +581,11 @@ describe.each([ ); expect( - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. await previous.evaluate((node) => node.getAttribute("aria-label")) ).toBe(labelName); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - async function assertLabelDoesNotExist(categoryName: any, labelName: any) { + async function assertLabelDoesNotExist(categoryName, labelName) { await expandCategory(categoryName); const result = await page.$( `[data-testid='categorical-value-${categoryName}-${labelName}']` diff --git a/client/__tests__/e2e/e2eJestConfig.json b/client/__tests__/e2e/e2eJestConfig.json index d3db4295..cc00d0db 100644 --- a/client/__tests__/e2e/e2eJestConfig.json +++ b/client/__tests__/e2e/e2eJestConfig.json @@ -1,10 +1,10 @@ { "testRunner": "jest-circus/runner", "preset": "jest-puppeteer", - "testMatch": ["**/__tests__/**/?(*.)(spec|test).ts?(x)"], - "setupFiles": ["../setupMissingGlobals.ts"], - "setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.ts"], - "globalSetup": "../globalSetup.ts", + "testMatch": ["**/__tests__/**/?(*.)(spec|test).js?(x)"], + "setupFiles": ["../setupMissingGlobals.js"], + "setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.js"], + "globalSetup": "../globalSetup.js", "globalTeardown": "jest-environment-puppeteer/teardown", "testEnvironment": "./screenshot_env.js" } diff --git a/client/__tests__/e2e/puppeteer.setup.ts b/client/__tests__/e2e/puppeteer.setup.js similarity index 85% rename from client/__tests__/e2e/puppeteer.setup.ts rename to client/__tests__/e2e/puppeteer.setup.js index a910f023..6c593b93 100644 --- a/client/__tests__/e2e/puppeteer.setup.ts +++ b/client/__tests__/e2e/puppeteer.setup.js @@ -23,7 +23,6 @@ beforeEach(async () => { const userAgent = await browser.userAgent(); 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 }); page.on("pageerror", (err) => { @@ -50,8 +49,7 @@ beforeEach(async () => { } const errorMsgText = await Promise.all( // TODO can we do this without internal properties? - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - msg.args().map((arg: any) => arg._remoteObject.description) + msg.args().map((arg) => arg._remoteObject.description) ); throw new Error(`Console error: ${errorMsgText}`); } diff --git a/client/__tests__/e2e/puppeteerUtils.js b/client/__tests__/e2e/puppeteerUtils.js new file mode 100644 index 00000000..8d3a497f --- /dev/null +++ b/client/__tests__/e2e/puppeteerUtils.js @@ -0,0 +1,131 @@ +/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ +export function getTestId(id) { + return `[data-testid='${id}']`; +} + +export function getTestClass(className) { + return `[data-testclass='${className}']`; +} + +export async function waitByID(testId, props = {}) { + return page.waitForSelector(getTestId(testId), props); +} + +export async function waitByClass(testClass, props = {}) { + return page.waitForSelector(`[data-testclass='${testClass}']`, props); +} + +export async function waitForAllByIds(testIds) { + await Promise.all( + testIds.map((testId) => page.waitForSelector(getTestId(testId))) + ); +} + +export async function getAllByClass(testClass) { + return page.$$(`[data-testclass=${testClass}]`); +} + +export async function typeInto(testId, text) { + // blueprint's typeahead is treating typing weird, clicking & waiting first solves this + // only works for text without special characters + await waitByID(testId); + const selector = getTestId(testId); + // type ahead can be annoying if you don't pause before you type + await page.click(selector); + await page.waitForTimeout(200); + await page.type(selector, text); +} + +export async function clearInputAndTypeInto(testId, text) { + await waitByID(testId); + const selector = getTestId(testId); + // only works for text without special characters + // type ahead can be annoying if you don't pause before you type + await page.click(selector); + await page.waitForTimeout(200); + // select all + await page.click(selector, { clickCount: 3 }); + await page.keyboard.press("Backspace"); + await page.type(selector, text); +} + +export async function clickOn(testId, options = {}) { + await expect(page).toClick(getTestId(testId), options); +} + +/** + * (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. + */ +export async function clickOnUntil(testId, assert) { + const MAX_RETRY = 10; + const WAIT_FOR_MS = 200; + + let retry = 0; + + while (retry < MAX_RETRY) { + try { + await clickOn(testId); + await assert(); + + break; + } catch (error) { + retry += 1; + + await page.waitForTimeout(WAIT_FOR_MS); + } + } + + if (retry === MAX_RETRY) { + throw Error("clickOnUntil() assertion failed!"); + } +} + +export async function getOneElementInnerHTML(selector, options = {}) { + await page.waitForSelector(selector, options); + + return page.$eval(selector, (el) => el.innerHTML); +} + +export async function getOneElementInnerText(selector) { + expect(page).toMatchElement(selector); + + return page.$eval(selector, (el) => el.innerText); +} + +export async function getElementCoordinates(testId) { + return page.$eval(getTestId(testId), (elem) => { + const { left, top } = elem.getBoundingClientRect(); + return [left, top]; + }); +} + +async function clickTermsOfService() { + if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return; + + await clickOn("tos-cookies-accept"); +} + +async function nameNewAnnotation() { + if (await isElementPresent(getTestId("annotation-dialog"))) { + await typeInto("new-annotation-name", "ignoreE2E"); + await clickOn("submit-annotation"); + + // wait for the page to load + await waitByClass("autosave-complete"); + } +} + +export async function goToPage(url) { + await page.goto(url, { + waitUntil: "networkidle0", + }); + + await nameNewAnnotation(); + await clickTermsOfService(); +} + +export async function isElementPresent(selector, options) { + return Boolean(await page.$(selector, options)); +} +/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/puppeteerUtils.ts b/client/__tests__/e2e/puppeteerUtils.ts deleted file mode 100644 index 6438adf6..00000000 --- a/client/__tests__/e2e/puppeteerUtils.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export function getTestId(id: any) { - return `[data-testid='${id}']`; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export function getTestClass(className: any) { - return `[data-testclass='${className}']`; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function waitByID(testId: any, props = {}) { - return page.waitForSelector(getTestId(testId), props); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function waitByClass(testClass: any, props = {}) { - return page.waitForSelector(`[data-testclass='${testClass}']`, props); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function waitForAllByIds(testIds: any) { - await Promise.all( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - testIds.map((testId: any) => page.waitForSelector(getTestId(testId))) - ); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getAllByClass(testClass: any) { - return page.$$(`[data-testclass=${testClass}]`); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function typeInto(testId: any, text: any) { - // blueprint's typeahead is treating typing weird, clicking & waiting first solves this - // only works for text without special characters - await waitByID(testId); - const selector = getTestId(testId); - // type ahead can be annoying if you don't pause before you type - await page.click(selector); - await page.waitForTimeout(200); - await page.type(selector, text); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function clearInputAndTypeInto(testId: any, text: any) { - await waitByID(testId); - const selector = getTestId(testId); - // only works for text without special characters - // type ahead can be annoying if you don't pause before you type - await page.click(selector); - await page.waitForTimeout(200); - // select all - await page.click(selector, { clickCount: 3 }); - await page.keyboard.press("Backspace"); - await page.type(selector, text); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function clickOn(testId: any, options = {}) { - await expect(page).toClick(getTestId(testId), options); -} - -/** - * (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. - */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function clickOnUntil(testId: any, assert: any) { - const MAX_RETRY = 10; - const WAIT_FOR_MS = 200; - - let retry = 0; - - while (retry < MAX_RETRY) { - try { - await clickOn(testId); - await assert(); - - break; - } catch (error) { - retry += 1; - - await page.waitForTimeout(WAIT_FOR_MS); - } - } - - if (retry === MAX_RETRY) { - throw Error("clickOnUntil() assertion failed!"); - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getOneElementInnerHTML(selector: any, options = {}) { - await page.waitForSelector(selector, options); - - return page.$eval(selector, (el) => el.innerHTML); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getOneElementInnerText(selector: any) { - expect(page).toMatchElement(selector); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - return page.$eval(selector, (el) => (el as any).innerText); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function getElementCoordinates(testId: any) { - return page.$eval(getTestId(testId), (elem) => { - const { left, top } = elem.getBoundingClientRect(); - return [left, top]; - }); -} - -async function clickTermsOfService() { - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return; - - await clickOn("tos-cookies-accept"); -} - -async function nameNewAnnotation() { - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - if (await isElementPresent(getTestId("annotation-dialog"))) { - await typeInto("new-annotation-name", "ignoreE2E"); - await clickOn("submit-annotation"); - - // wait for the page to load - await waitByClass("autosave-complete"); - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -export async function goToPage(url: any) { - await page.goto(url, { - waitUntil: "networkidle0", - }); - - await nameNewAnnotation(); - await clickTermsOfService(); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -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)); -} -/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/screenshot_env.js b/client/__tests__/e2e/screenshot_env.js index 742579d1..4701d8ca 100644 --- a/client/__tests__/e2e/screenshot_env.js +++ b/client/__tests__/e2e/screenshot_env.js @@ -1,11 +1,7 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const PuppeteerEnvironment = require("jest-environment-puppeteer"); require("jest-circus"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. 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 -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const takeScreenshot = require("./takeScreenshot"); class ScreenshotEnvironment extends PuppeteerEnvironment { diff --git a/client/__tests__/globalSetup.ts b/client/__tests__/globalSetup.js similarity index 60% rename from client/__tests__/globalSetup.ts rename to client/__tests__/globalSetup.js index 6fdfed94..e5163056 100644 --- a/client/__tests__/globalSetup.ts +++ b/client/__tests__/globalSetup.js @@ -1,12 +1,8 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment --- FIXME: disabled temporarily on migrate to TS. -// @ts-ignore FIXME: 'globalSetup.ts' cannot be compiled under '--isola... Remove this comment to see the full error message const { SecretsManagerClient, GetSecretValueCommand, - // eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. } = require("@aws-sdk/client-secrets-manager"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const { setup } = require("jest-environment-puppeteer"); const client = new SecretsManagerClient({ region: "us-west-2" }); diff --git a/client/__tests__/reducers/cascade.test.ts b/client/__tests__/reducers/cascade.test.js similarity index 51% rename from client/__tests__/reducers/cascade.test.ts rename to client/__tests__/reducers/cascade.test.js index 4b086881..a61e579e 100644 --- a/client/__tests__/reducers/cascade.test.ts +++ b/client/__tests__/reducers/cascade.test.js @@ -20,16 +20,7 @@ describe("cascade", () => { const reducer = cascadeReducers([ [ "foo", - ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - currentState: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - nextSharedState: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - prevSharedState: any - ) => { + (currentState, action, nextSharedState, prevSharedState) => { expect(currentState).toBeUndefined(); expect(action).toEqual(topLevelAction); expect(nextSharedState).toStrictEqual({}); @@ -39,16 +30,7 @@ describe("cascade", () => { ], [ "bar", - ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - currentState: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - nextSharedState: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - prevSharedState: any - ) => { + (currentState, action, nextSharedState, prevSharedState) => { expect(currentState).toBeUndefined(); expect(action).toEqual(topLevelAction); expect(nextSharedState).toStrictEqual({ foo: 0 }); diff --git a/client/__tests__/reducers/genesets.test.ts b/client/__tests__/reducers/genesets.test.js similarity index 97% rename from client/__tests__/reducers/genesets.test.ts rename to client/__tests__/reducers/genesets.test.js index ede5a758..ad377f6c 100644 --- a/client/__tests__/reducers/genesets.test.ts +++ b/client/__tests__/reducers/genesets.test.js @@ -501,7 +501,6 @@ describe("geneset: set tid", () => { test("not a number error", () => { expect(() => { 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 }, { type: "geneset: set tid", @@ -514,7 +513,6 @@ describe("geneset: set tid", () => { test("decrement error", () => { expect(() => { 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 }, { type: "geneset: set tid", diff --git a/client/__tests__/reducers/genesetsUI.test.ts b/client/__tests__/reducers/genesetsUI.test.js similarity index 100% rename from client/__tests__/reducers/genesetsUI.test.ts rename to client/__tests__/reducers/genesetsUI.test.js diff --git a/client/__tests__/reducers/undoable.test.ts b/client/__tests__/reducers/undoable.test.js similarity index 86% rename from client/__tests__/reducers/undoable.test.ts rename to client/__tests__/reducers/undoable.test.js index d58913cc..99a42f24 100644 --- a/client/__tests__/reducers/undoable.test.ts +++ b/client/__tests__/reducers/undoable.test.js @@ -1,12 +1,9 @@ -import { Reducer } from "redux"; import undoable from "../../src/reducers/undoable"; describe("create", () => { test("no keys", () => { - expect(() => - undoable(() => {}, undefined as unknown as string[]) - ).toThrow(); - expect(() => undoable(() => {}, null as unknown as string[])).toThrow(); + expect(() => undoable(() => {})).toThrow(); + expect(() => undoable(() => {}, null)).toThrow(); expect(() => undoable(() => {}, [])).toThrow(); expect(() => undoable(() => {}, [], {})).toThrow(); }); @@ -26,7 +23,7 @@ describe("create", () => { describe("undo", () => { test("expected state modifications", () => { const initialState = { a: 0, b: 1000 }; - const reducer: Reducer = (state) => ({ a: state.a + 1, b: state.b + 1 }); + const reducer = (state) => ({ a: state.a + 1, b: state.b + 1 }); const undoableReducer = undoable(reducer, ["a"]); const s1 = undoableReducer(initialState, { type: "test" }); @@ -44,8 +41,8 @@ describe("undo", () => { describe("redo", () => { const initialState = { a: 0, b: 1000 }; - const reducer: Reducer = (state) => ({ a: state.a + 1, b: state.b + 1 }); - let UR: Reducer; + const reducer = (state) => ({ a: state.a + 1, b: state.b + 1 }); + let UR; beforeEach(() => { UR = undoable(reducer, ["a"]); diff --git a/client/__tests__/setupMissingGlobals.ts b/client/__tests__/setupMissingGlobals.js similarity index 61% rename from client/__tests__/setupMissingGlobals.ts rename to client/__tests__/setupMissingGlobals.js index 72d14319..679cc21f 100644 --- a/client/__tests__/setupMissingGlobals.ts +++ b/client/__tests__/setupMissingGlobals.js @@ -5,6 +5,5 @@ the jest test environment). 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.TextEncoder = TextEncoder; diff --git a/client/__tests__/util/actionHelpers.test.ts b/client/__tests__/util/actionHelpers.test.js similarity index 91% rename from client/__tests__/util/actionHelpers.test.ts rename to client/__tests__/util/actionHelpers.test.js index e6ab9da3..33475309 100644 --- a/client/__tests__/util/actionHelpers.test.ts +++ b/client/__tests__/util/actionHelpers.test.js @@ -11,18 +11,14 @@ describe("rangeEncodeIndices", () => { test("sorted flag", () => { expect(rangeEncodeIndices([1, 9, 432], 10, true)).toMatchObject([ - 1, - 9, - 432, + 1, 9, 432, ]); expect(rangeEncodeIndices([1, 9, 432], 10, false)).toMatchObject([ - 1, - 9, - 432, + 1, 9, 432, ]); - expect( - rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, true) - ).toMatchObject([[0, 3], [9, 10], 432]); + expect(rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, true)).toMatchObject( + [[0, 3], [9, 10], 432] + ); expect( rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, false) ).toMatchObject([[0, 3], [9, 10], 432]); diff --git a/client/__tests__/util/annoMatrix/annoMatrix.test.ts b/client/__tests__/util/annoMatrix/annoMatrix.test.js similarity index 56% rename from client/__tests__/util/annoMatrix/annoMatrix.test.ts rename to client/__tests__/util/annoMatrix/annoMatrix.test.js index c8f786de..c178a5f7 100644 --- a/client/__tests__/util/annoMatrix/annoMatrix.test.ts +++ b/client/__tests__/util/annoMatrix/annoMatrix.test.js @@ -10,18 +10,14 @@ import { isubsetMask, } from "../../../src/annoMatrix"; import { Dataframe } from "../../../src/util/dataframe"; -import { Field } from "../../../src/common/types/schema"; enableFetchMocks(); describe("AnnoMatrix", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let annoMatrix: any; + let annoMatrix; beforeEach(async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).resetMocks(); // reset all fetch mocking state - // reset all fetch mocking state + fetch.resetMocks(); // reset all fetch mocking state annoMatrix = new AnnoMatrixLoader( serverMocks.baseDataURL, serverMocks.schema.schema @@ -35,67 +31,58 @@ describe("AnnoMatrix", () => { expect(annoMatrix.nObs).toEqual(serverMocks.schema.schema.dataframe.nObs); expect(annoMatrix.nVar).toEqual(serverMocks.schema.schema.dataframe.nVar); expect(annoMatrix.isView).toBeFalsy(); - expect(annoMatrix.viewOf).toBe(annoMatrix); + expect(annoMatrix.viewOf).toBeUndefined(); expect(annoMatrix.rowIndex).toBeDefined(); }); test("simple single column fetch", async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once(serverMocks.annotationsObs(["name_0"])); + fetch.once(serverMocks.annotationsObs(["name_0"])); - const df = await annoMatrix.fetch(Field.obs, "name_0"); + const df = await annoMatrix.fetch("obs", "name_0"); expect(df).toBeInstanceOf(Dataframe); expect(df.colIndex.labels()).toEqual(["name_0"]); expect(df.dims).toEqual([annoMatrix.nObs, 1]); }); test("simple multi column fetch", async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any) + fetch .once(serverMocks.annotationsObs(["name_0"])) .once(serverMocks.annotationsObs(["n_genes"])); await expect( - annoMatrix.fetch(Field.obs, ["name_0", "n_genes"]) + annoMatrix.fetch("obs", ["name_0", "n_genes"]) ).resolves.toBeInstanceOf(Dataframe); }); describe("fetch from field", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const getLastTwo = async (field: any) => { + const getLastTwo = async (field) => { const columnNames = annoMatrix.getMatrixColumns(field).slice(-2); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockResponses( - ...columnNames.map(() => serverMocks.responder) - ); + fetch.mockResponses(...columnNames.map(() => serverMocks.responder)); await expect( annoMatrix.fetch(field, columnNames) ).resolves.toBeInstanceOf(Dataframe); }; - test(Field.obs, async () => getLastTwo(Field.obs)); + test("obs", async () => getLastTwo("obs")); test("var", async () => getLastTwo("var")); test("emb", async () => getLastTwo("emb")); }); test("fetch - test all query forms", async () => { // single string is a column name - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once(serverMocks.annotationsObs(["n_genes"])); - await expect( - annoMatrix.fetch(Field.obs, "n_genes") - ).resolves.toBeInstanceOf(Dataframe); + fetch.once(serverMocks.annotationsObs(["n_genes"])); + await expect(annoMatrix.fetch("obs", "n_genes")).resolves.toBeInstanceOf( + Dataframe + ); // array of column names, expecting n_genes to be cached. - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once(serverMocks.annotationsObs(["percent_mito"])); + fetch.once(serverMocks.annotationsObs(["percent_mito"])); await expect( - annoMatrix.fetch(Field.obs, ["n_genes", "percent_mito"]) + annoMatrix.fetch("obs", ["n_genes", "percent_mito"]) ).resolves.toBeInstanceOf(Dataframe); // more complex value filter query, enumerated - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once(serverMocks.responder); + fetch.once(serverMocks.responder); await expect( annoMatrix.fetch("X", { where: { @@ -108,8 +95,7 @@ describe("AnnoMatrix", () => { // more complex value filter query, range const varIndex = annoMatrix.schema.annotations.var.index; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any) + fetch .once( serverMocks.withExpected("/data/var", [[`var:${varIndex}`, "SUMO3"]]) ) @@ -152,9 +138,9 @@ describe("AnnoMatrix", () => { test("schema accessors", () => { expect(annoMatrix.getMatrixFields()).toEqual( - expect.arrayContaining(["X", Field.obs, "emb", "var"]) + expect.arrayContaining(["X", "obs", "emb", "var"]) ); - expect(annoMatrix.getMatrixColumns(Field.obs)).toEqual( + expect(annoMatrix.getMatrixColumns("obs")).toEqual( expect.arrayContaining(["name_0", "n_genes", "louvain"]) ); expect(annoMatrix.getColumnSchema("emb", "umap")).toEqual({ @@ -172,7 +158,7 @@ describe("AnnoMatrix", () => { test the mask & label access to subset via isubset and isubsetMask */ test("isubset", async () => { - const rowList = new Int32Array([0, 10]); + const rowList = [0, 10]; const rowMask = new Uint8Array(annoMatrix.nObs); for (let i = 0; i < rowList.length; i += 1) { rowMask[rowList[i]] = 1; @@ -185,14 +171,11 @@ describe("AnnoMatrix", () => { expect(am1.nObs).toEqual(am2.nObs); expect(am1.nVar).toEqual(am2.nVar); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any) + fetch .once(serverMocks.annotationsObs(["n_genes"])) .once(serverMocks.annotationsObs(["n_genes"])); - const ng1 = (await am1.fetch(Field.obs, "n_genes")) as Dataframe; - const ng2 = (await am2.fetch(Field.obs, "n_genes")) as Dataframe; - expect(ng1).toBeDefined(); - expect(ng2).toBeDefined(); + const ng1 = await am1.fetch("obs", "n_genes"); + const ng2 = await am2.fetch("obs", "n_genes"); expect(ng1).toHaveLength(ng2.length); expect(ng1.colIndex.labels()).toEqual(ng2.colIndex.labels()); expect(ng1.col("n_genes").asArray()).toEqual( @@ -202,12 +185,10 @@ describe("AnnoMatrix", () => { }); describe("add/drop column", () => { - // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type. async function addDrop(base) { - expect(base.getMatrixColumns(Field.obs)).not.toContain("foo"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect(base.fetch(Field.obs, "foo")).rejects.toThrow( + expect(base.getMatrixColumns("obs")).not.toContain("foo"); + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(base.fetch("obs", "foo")).rejects.toThrow( "unknown column name" ); @@ -217,9 +198,9 @@ describe("AnnoMatrix", () => { Float32Array, 0 ); - expect(base.getMatrixColumns(Field.obs)).not.toContain("foo"); - expect(am1.getMatrixColumns(Field.obs)).toContain("foo"); - const foo: Dataframe = await am1.fetch(Field.obs, "foo"); + expect(base.getMatrixColumns("obs")).not.toContain("foo"); + expect(am1.getMatrixColumns("obs")).toContain("foo"); + const foo = await am1.fetch("obs", "foo"); expect(foo).toBeDefined(); expect(foo).toBeInstanceOf(Dataframe); expect(foo).toHaveLength(am1.nObs); @@ -229,11 +210,10 @@ describe("AnnoMatrix", () => { /* drop */ const am2 = am1.dropObsColumn("foo"); - expect(base.getMatrixColumns(Field.obs)).not.toContain("foo"); - expect(am2.getMatrixColumns(Field.obs)).not.toContain("foo"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect(am2.fetch(Field.obs, "foo")).rejects.toThrow( + expect(base.getMatrixColumns("obs")).not.toContain("foo"); + expect(am2.getMatrixColumns("obs")).not.toContain("foo"); + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(am2.fetch("obs", "foo")).rejects.toThrow( "unknown column name" ); } @@ -246,25 +226,23 @@ describe("AnnoMatrix", () => { const am1 = clip(annoMatrix, 0.1, 0.9); await addDrop(am1); - const am2 = isubset(am1, new Int32Array([0, 1, 2, 20, 30, 400])); + const am2 = isubset(am1, [0, 1, 2, 20, 30, 400]); await addDrop(am2); - const am3 = isubset(annoMatrix, new Int32Array([10, 0, 7, 3])); + const am3 = isubset(annoMatrix, [10, 0, 7, 3]); await addDrop(am3); const am4 = clip(am3, 0, 1); await addDrop(am4); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockResponse(serverMocks.responder); + fetch.mockResponse(serverMocks.responder); - await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs)); - await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs)); - await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs)); - await am4.fetch(Field.obs, am4.getMatrixColumns(Field.obs)); + await am1.fetch("obs", am1.getMatrixColumns("obs")); + await am2.fetch("obs", am2.getMatrixColumns("obs")); + await am3.fetch("obs", am3.getMatrixColumns("obs")); + await am4.fetch("obs", am4.getMatrixColumns("obs")); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).resetMocks(); + fetch.resetMocks(); await addDrop(am1); await addDrop(am2); @@ -274,7 +252,6 @@ describe("AnnoMatrix", () => { }); describe("setObsColumnValues", () => { - // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type. async function addSetDrop(base) { /* add column */ let am = base.addObsColumn( @@ -288,7 +265,7 @@ describe("AnnoMatrix", () => { "unassigned" ); - const testVal = await am.fetch(Field.obs, "test"); + const testVal = await am.fetch("obs", "test"); expect(testVal.col("test").asArray()).toEqual( new Array(am.nObs).fill("unassigned") ); @@ -296,7 +273,7 @@ describe("AnnoMatrix", () => { /* set values in column */ const whichRows = [1, 2, 10]; const am1 = await am.setObsColumnValues("test", whichRows, "yo"); - const testVal1 = await am1.fetch(Field.obs, "test"); + const testVal1 = await am1.fetch("obs", "test"); const expt = new Array(am1.nObs).fill("unassigned"); for (let i = 0; i < whichRows.length; i += 1) { const offset = am1.rowIndex.getOffset(whichRows[i]); @@ -304,16 +281,15 @@ describe("AnnoMatrix", () => { } expect(testVal1).not.toBe(testVal); expect(testVal1.col("test").asArray()).toEqual(expt); - expect(am1.getColumnSchema(Field.obs, "test").type).toBe("categorical"); - expect(am1.getColumnSchema(Field.obs, "test").categories).toEqual( + expect(am1.getColumnSchema("obs", "test").type).toBe("categorical"); + expect(am1.getColumnSchema("obs", "test").categories).toEqual( expect.arrayContaining(["unassigned", "red", "green", "yo"]) ); /* drop column */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); + fetch.mockRejectOnce(new Error("unknown column name")); am = am1.dropObsColumn("test"); - await expect(am.fetch(Field.obs, "test")).rejects.toThrow( + await expect(am.fetch("obs", "test")).rejects.toThrow( "unknown column name" ); } @@ -326,18 +302,17 @@ describe("AnnoMatrix", () => { const am1 = clip(annoMatrix, 0.1, 0.9); await addSetDrop(am1); - const am2 = isubset(am1, new Int32Array([0, 1, 2, 10, 20, 30, 400])); + const am2 = isubset(am1, [0, 1, 2, 10, 20, 30, 400]); await addSetDrop(am2); - const am3 = isubset(annoMatrix, new Int32Array([10, 1, 0, 30, 2])); + const am3 = isubset(annoMatrix, [10, 1, 0, 30, 2]); await addSetDrop(am3); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockResponse(serverMocks.responder); + fetch.mockResponse(serverMocks.responder); - await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs)); - await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs)); - await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs)); + await am1.fetch("obs", am1.getMatrixColumns("obs")); + await am2.fetch("obs", am2.getMatrixColumns("obs")); + await am3.fetch("obs", am3.getMatrixColumns("obs")); await addSetDrop(am1); await addSetDrop(am2); diff --git a/client/__tests__/util/annoMatrix/crossfilter.test.ts b/client/__tests__/util/annoMatrix/crossfilter.test.js similarity index 56% rename from client/__tests__/util/annoMatrix/crossfilter.test.ts rename to client/__tests__/util/annoMatrix/crossfilter.test.js index 4d3d6364..873334ca 100644 --- a/client/__tests__/util/annoMatrix/crossfilter.test.ts +++ b/client/__tests__/util/annoMatrix/crossfilter.test.js @@ -12,25 +12,19 @@ import { AnnoMatrixObsCrossfilter, isubsetMask, } from "../../../src/annoMatrix"; -import { Dataframe } from "../../../src/util/dataframe"; import { rangeFill } from "../../../src/util/range"; -import { Field, Schema } from "../../../src/common/types/schema"; enableFetchMocks(); describe("AnnoMatrixCrossfilter", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let annoMatrix: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let crossfilter: any; + let annoMatrix; + let crossfilter; beforeEach(async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).resetMocks(); // reset all fetch mocking state - // reset all fetch mocking state + fetch.resetMocks(); // reset all fetch mocking state annoMatrix = new AnnoMatrixLoader( serverMocks.baseDataURL, - serverMocks.schema.schema as Schema + serverMocks.schema.schema ); crossfilter = new AnnoMatrixObsCrossfilter(annoMatrix); }); @@ -73,11 +67,8 @@ describe("AnnoMatrixCrossfilter", () => { crossfilter.obsCrossfilter.hasDimension("obs/louvain") ).toBeFalsy(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( - serverMocks.dataframeResponse(["louvain"], [obsLouvain]) - ); - let newCrossfilter = await crossfilter.select(Field.obs, "louvain", { + fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); + let newCrossfilter = await crossfilter.select("obs", "louvain", { mode: "none", }); @@ -85,10 +76,9 @@ describe("AnnoMatrixCrossfilter", () => { expect( newCrossfilter.obsCrossfilter.hasDimension("obs/louvain") ).toBeTruthy(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - expect((fetch as any).mock.calls).toHaveLength(1); + expect(fetch.mock.calls).toHaveLength(1); - newCrossfilter = await crossfilter.select(Field.obs, "louvain", { + newCrossfilter = await crossfilter.select("obs", "louvain", { mode: "all", }); expect(newCrossfilter.countSelected()).toEqual(annoMatrix.nObs); @@ -97,11 +87,8 @@ describe("AnnoMatrixCrossfilter", () => { test("simple column select", async () => { let xfltr; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( - serverMocks.dataframeResponse(["louvain"], [obsLouvain]) - ); - xfltr = await crossfilter.select(Field.obs, "louvain", { + fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); + xfltr = await crossfilter.select("obs", "louvain", { mode: "exact", values: ["NK cells", "B cells"], }); @@ -118,7 +105,6 @@ describe("AnnoMatrixCrossfilter", () => { expect(xfltr.allSelectedLabels()).toEqual( Int32Array.from( 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); return acc; }, []) @@ -134,20 +120,17 @@ describe("AnnoMatrixCrossfilter", () => { ) ); - const df: Dataframe = await annoMatrix.fetch(Field.obs, "louvain"); + const df = await annoMatrix.fetch("obs", "louvain"); const values = df.col("louvain").asArray(); const selected = xfltr.allSelectedMask(); values.every( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (val: any, idx: any) => - !["NK cells", "B cells"].includes(val) !== !selected[idx] + (val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx] ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( + fetch.once( serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)]) ); - xfltr = await xfltr.select(Field.obs, "n_genes", { + xfltr = await xfltr.select("obs", "n_genes", { mode: "range", lo: 0, hi: 500, @@ -163,7 +146,6 @@ describe("AnnoMatrixCrossfilter", () => { val < 500 && (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); return acc; }, []) @@ -178,8 +160,7 @@ describe("AnnoMatrixCrossfilter", () => { const varIndex = annoMatrix.schema.annotations.var.index; const { nObs } = annoMatrix.schema.dataframe; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( + fetch.once( serverMocks.dataframeResponse( ["TEST"], [rangeFill(new Float32Array(nObs), 0, 0.1)] @@ -215,19 +196,14 @@ describe("AnnoMatrixCrossfilter", () => { }); const values = df.icol(0).asArray(); const selected = xfltr.allSelectedMask(); - values.every( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (val: any, idx: any) => !(val >= 0 && val <= 50) !== !selected[idx] + values.every((val, idx) => !(val >= 0 && val <= 50) !== !selected[idx]); + expect(selected.reduce((acc, val) => (val ? acc + 1 : acc), 0)).toEqual( + xfltr.countSelected() ); - expect( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - selected.reduce((acc: any, val: any) => (val ? acc + 1 : acc), 0) - ).toEqual(xfltr.countSelected()); }); test("spatial column select", async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( + fetch.once( serverMocks.dataframeResponse( ["umap_0", "umap_1"], [Float32Array.from(embUmap[0]), Float32Array.from(embUmap[1])] @@ -246,7 +222,6 @@ describe("AnnoMatrixCrossfilter", () => { test("select on subset", async () => { const mask = new Uint8Array(annoMatrix.nObs).fill(0); 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; } const annoMatrixSubset = isubsetMask(annoMatrix, mask); @@ -255,11 +230,8 @@ describe("AnnoMatrixCrossfilter", () => { let xfltr = new AnnoMatrixObsCrossfilter(annoMatrixSubset); expect(xfltr.countSelected()).toEqual(annoMatrixSubset.nObs); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( - serverMocks.dataframeResponse(["louvain"], [obsLouvain]) - ); - xfltr = await xfltr.select(Field.obs, "louvain", { + fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); + xfltr = await xfltr.select("obs", "louvain", { mode: "exact", values: ["NK cells", "B cells"], }); @@ -267,17 +239,11 @@ describe("AnnoMatrixCrossfilter", () => { expect(xfltr).toBeDefined(); expect(xfltr.countSelected()).toEqual(240); - const df: Dataframe = (await annoMatrixSubset.fetch( - Field.obs, - "louvain" - )) as Dataframe; - expect(df).toBeDefined(); + const df = await annoMatrixSubset.fetch("obs", "louvain"); const values = df.col("louvain").asArray(); const selected = xfltr.allSelectedMask(); values.every( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (val: any, idx: any) => - !["NK cells", "B cells"].includes(val) !== !selected[idx] + (val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx] ); }); @@ -290,9 +256,8 @@ describe("AnnoMatrixCrossfilter", () => { "unable to obsSelect upon the var dimension" ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect(crossfilter.select(Field.obs, "foo")).rejects.toThrow( + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(crossfilter.select("obs", "foo")).rejects.toThrow( "unknown column name" ); }); @@ -302,32 +267,27 @@ describe("AnnoMatrixCrossfilter", () => { /* test the matrix mutators via crossfilter proxy */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - async function helperAddTestCol(cf: any, colName: any, colSchema = null) { + async function helperAddTestCol(cf, colName, colSchema = null) { expect( - cf.annoMatrix.getMatrixColumns(Field.obs).includes(colName) + cf.annoMatrix.getMatrixColumns("obs").includes(colName) ).toBeFalsy(); 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 = { name: colName, type: "categorical", categories: ["toasty"], }; } - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. colSchema.name = colName; - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. const initValue = colSchema.categories[0]; const xfltr = cf.addObsColumn(colSchema, Array, initValue); expect( xfltr.annoMatrix.schema.annotations.obs.columns.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (v: any) => v.name === colName + (v) => v.name === colName ) ).toHaveLength(1); - const df = await xfltr.annoMatrix.fetch(Field.obs, colName); + const df = await xfltr.annoMatrix.fetch("obs", colName); expect(df.hasCol(colName)).toBeTruthy(); return xfltr; } @@ -335,7 +295,7 @@ describe("AnnoMatrixCrossfilter", () => { test("addObsColumn", async () => { expect(crossfilter.countSelected()).toBe(annoMatrix.nObs); expect( - crossfilter.annoMatrix.getMatrixColumns(Field.obs).includes("foo") + crossfilter.annoMatrix.getMatrixColumns("obs").includes("foo") ).toBeFalsy(); const xfltr = crossfilter.addObsColumn( { name: "foo", type: "categorical", categories: ["A"] }, @@ -346,7 +306,7 @@ describe("AnnoMatrixCrossfilter", () => { // check schema updates correctly. expect(xfltr.countSelected()).toBe(annoMatrix.nObs); expect( - xfltr.annoMatrix.getMatrixColumns(Field.obs).includes("foo") + xfltr.annoMatrix.getMatrixColumns("obs").includes("foo") ).toBeTruthy(); expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toMatchObject({ name: "foo", @@ -354,18 +314,17 @@ describe("AnnoMatrixCrossfilter", () => { }); expect( xfltr.annoMatrix.schema.annotations.obs.columns.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (v: any) => v.name === "foo" + (v) => v.name === "foo" ) ).toHaveLength(1); // check data update. - const df: Dataframe = await xfltr.annoMatrix.fetch(Field.obs, "foo"); + const df = await xfltr.annoMatrix.fetch("obs", "foo"); expect( df .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .every((v: any) => v === "A") + .asArray() + .every((v) => v === "A") ).toBeTruthy(); // check that we catch dups @@ -402,30 +361,27 @@ describe("AnnoMatrixCrossfilter", () => { xfltr = xfltr.dropObsColumn("foo"); expect( xfltr.annoMatrix.schema.annotations.obs.columns.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (v: any) => v.name === "foo" + (v) => v.name === "foo" ) ).toHaveLength(0); expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow( + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( "unknown column name" ); // now same, but ensure we have built an index before doing the drop xfltr = await helperAddTestCol(crossfilter, "bar"); - xfltr = await xfltr.select(Field.obs, "bar", { + xfltr = await xfltr.select("obs", "bar", { mode: "exact", values: "whatever", }); xfltr = xfltr.dropObsColumn("bar"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect( - xfltr.select(Field.obs, "bar", { mode: "all" }) - ).rejects.toThrow("unknown column name"); + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow( + "unknown column name" + ); }); test("renameObsColumn", async () => { @@ -442,43 +398,38 @@ describe("AnnoMatrixCrossfilter", () => { // add a column, then rename it. xfltr = await helperAddTestCol(crossfilter, "foo"); xfltr = xfltr.renameObsColumn("foo", "bar"); - expect( - xfltr.annoMatrix.getColumnSchema(Field.obs, "foo") - ).toBeUndefined(); - expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({ + expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toBeUndefined(); + expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({ name: "bar", type: "categorical", }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); - await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow( + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( "unknown column name" ); - const df = await xfltr.annoMatrix.fetch(Field.obs, "bar"); + const df = await xfltr.annoMatrix.fetch("obs", "bar"); expect(df.hasCol("bar")).toBeTruthy(); // now same, but ensure we have built an index before doing the rename xfltr = await helperAddTestCol(crossfilter, "bar"); - xfltr = await xfltr.select(Field.obs, "bar", { + xfltr = await xfltr.select("obs", "bar", { mode: "exact", values: "whatever", }); xfltr = xfltr.renameObsColumn("bar", "xyz"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).mockRejectOnce(new Error("unknown column name")); + fetch.mockRejectOnce(new Error("unknown column name")); + await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow( + "unknown column name" + ); await expect( - xfltr.select(Field.obs, "bar", { mode: "all" }) - ).rejects.toThrow("unknown column name"); - await expect( - xfltr.select(Field.obs, "xyz", { mode: "none" }) + xfltr.select("obs", "xyz", { mode: "none" }) ).resolves.toBeInstanceOf(AnnoMatrixObsCrossfilter); }); test("addObsAnnoCategory", async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let xfltr: any; + let xfltr; // catch unknown or readonly columns expect(() => crossfilter.addObsAnnoCategory("louvain", "mumble")).toThrow( @@ -489,14 +440,13 @@ describe("AnnoMatrixCrossfilter", () => { ).toThrow("Unknown or readonly obs column"); // 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", { name: "foo", type: "categorical", categories: ["unassigned"], }); xfltr = xfltr.addObsAnnoCategory("foo", "a-new-label"); - expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({ + expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ name: "foo", type: "categorical", categories: expect.arrayContaining(["a-new-label", "unassigned"]), @@ -508,18 +458,17 @@ describe("AnnoMatrixCrossfilter", () => { ); // 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", { name: "bar", type: "categorical", categories: ["unassigned"], }); - xfltr = await xfltr.select(Field.obs, "bar", { + xfltr = await xfltr.select("obs", "bar", { mode: "exact", values: "something", }); xfltr = xfltr.addObsAnnoCategory("bar", "a-new-label"); - expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({ + expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({ name: "bar", type: "categorical", categories: expect.arrayContaining(["a-new-label", "unassigned"]), @@ -537,20 +486,19 @@ describe("AnnoMatrixCrossfilter", () => { crossfilter.removeObsAnnoCategory("undefined-name", "mumble") ).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", { name: "foo", type: "categorical", categories: ["unassigned", "red", "green", "blue"], }); - xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" }); + xfltr = await xfltr.select("obs", "foo", { mode: "all" }); expect( - (await xfltr.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .every((v: any) => v === "unassigned") + .asArray() + .every((v) => v === "unassigned") ).toBeTruthy(); - expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({ + expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ name: "foo", type: "categorical", categories: expect.arrayContaining([ @@ -564,23 +512,21 @@ describe("AnnoMatrixCrossfilter", () => { // remove an unused category const xfltr1 = await xfltr.removeObsAnnoCategory("foo", "red", "mumble"); expect( - (await xfltr1.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr1.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .every((v: any) => v === "unassigned") + .asArray() + .every((v) => v === "unassigned") ).toBeTruthy(); - expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject( - { - name: "foo", - type: "categorical", - categories: expect.arrayContaining([ - "unassigned", - "green", - "blue", - "mumble", - ]), - } - ); + expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ + name: "foo", + type: "categorical", + categories: expect.arrayContaining([ + "unassigned", + "green", + "blue", + "mumble", + ]), + }); // remove a used category const xfltr2 = await xfltr.removeObsAnnoCategory( @@ -589,18 +535,16 @@ describe("AnnoMatrixCrossfilter", () => { "red" ); expect( - (await xfltr2.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr2.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .every((v: any) => v === "red") + .asArray() + .every((v) => v === "red") ).toBeTruthy(); - expect(xfltr2.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject( - { - name: "foo", - type: "categorical", - categories: expect.arrayContaining(["green", "blue", "red"]), - } - ); + expect(xfltr2.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ + name: "foo", + type: "categorical", + categories: expect.arrayContaining(["green", "blue", "red"]), + }); }); test("setObsColumnValues", async () => { @@ -612,13 +556,12 @@ describe("AnnoMatrixCrossfilter", () => { crossfilter.setObsColumnValues("undefined-name", [0], "mumble") ).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", { name: "foo", type: "categorical", categories: ["unassigned", "red", "green", "blue"], }); - xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" }); + xfltr = await xfltr.select("obs", "foo", { mode: "all" }); // catch unknown row label await expect(() => @@ -627,43 +570,40 @@ describe("AnnoMatrixCrossfilter", () => { // set a few rows expect( - (await xfltr.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .every((v: any) => v === "unassigned") + .asArray() + .every((v) => v === "unassigned") ).toBeTruthy(); const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple"); expect( - (await xfltr1.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr1.annoMatrix.fetch("obs", "foo")) .col("foo") .asArray() .every( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (v: any, i: any) => + (v, i) => v === "unassigned" || (v === "purple" && (i === 0 || i === 10)) ) ).toBeTruthy(); - expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject( - { - name: "foo", - type: "categorical", - categories: expect.arrayContaining([ - "unassigned", - "red", - "green", - "blue", - "purple", - ]), - } - ); + expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ + name: "foo", + type: "categorical", + categories: expect.arrayContaining([ + "unassigned", + "red", + "green", + "blue", + "purple", + ]), + }); expect(xfltr1.countSelected()).toEqual(xfltr1.annoMatrix.nObs); - const xfltr2 = await xfltr1.select(Field.obs, "foo", { + const xfltr2 = await xfltr1.select("obs", "foo", { mode: "exact", values: ["purple"], }); expect(xfltr2.countSelected()).toEqual(2); - expect(xfltr2.allSelectedLabels()).toEqual(Array.from([0, 10])); + expect(xfltr2.allSelectedLabels()).toEqual(Int32Array.from([0, 10])); }); test("resetObsColumnValues", async () => { @@ -675,13 +615,12 @@ describe("AnnoMatrixCrossfilter", () => { crossfilter.resetObsColumnValues("undefined-name", "red", "blue") ).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", { name: "foo", type: "categorical", categories: ["unassigned", "red", "green", "blue"], }); - xfltr = await xfltr.select(Field.obs, "foo", { + xfltr = await xfltr.select("obs", "foo", { mode: "exact", values: "red", }); @@ -692,60 +631,54 @@ describe("AnnoMatrixCrossfilter", () => { ).rejects.toThrow("unknown category"); let xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple"); - xfltr1 = await xfltr1.select(Field.obs, "foo", { + xfltr1 = await xfltr1.select("obs", "foo", { mode: "exact", values: "purple", }); expect( - (await xfltr1.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr1.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((v: any) => v === "purple") + .asArray() + .filter((v) => v === "purple") ).toHaveLength(2); xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta"); expect( - (await xfltr1.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr1.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((v: any) => v === "magenta") + .asArray() + .filter((v) => v === "magenta") ).toHaveLength(2); expect( - (await xfltr1.annoMatrix.fetch(Field.obs, "foo")) + (await xfltr1.annoMatrix.fetch("obs", "foo")) .col("foo") - .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((v: any) => v === "purple") + .asArray() + .filter((v) => v === "purple") ).toHaveLength(0); - expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject( - { - name: "foo", - type: "categorical", - categories: expect.arrayContaining([ - "unassigned", - "red", - "green", - "blue", - "purple", - "magenta", - ]), - } - ); + expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ + name: "foo", + type: "categorical", + categories: expect.arrayContaining([ + "unassigned", + "red", + "green", + "blue", + "purple", + "magenta", + ]), + }); }); }); describe("edge cases", () => { test("transition from empty annoMatrix", async () => { // select before fetch needs to work - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (fetch as any).once( - serverMocks.dataframeResponse(["louvain"], [obsLouvain]) - ); - const xfltr = await crossfilter.select(Field.obs, "louvain", { + fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain])); + const xfltr = await crossfilter.select("obs", "louvain", { mode: "exact", values: "B cells", }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - expect((fetch as any).mock.calls).toHaveLength(1); + expect(fetch.mock.calls).toHaveLength(1); expect(xfltr.obsCrossfilter.hasDimension("obs/louvain")).toBeTruthy(); expect(xfltr.obsCrossfilter.all()).toBe(xfltr.annoMatrix._cache.obs); expect(xfltr.countSelected()).toEqual( diff --git a/client/__tests__/util/annoMatrix/n_genes.json b/client/__tests__/util/annoMatrix/n_genes.json index 29a4fece..89227d5f 100644 --- a/client/__tests__/util/annoMatrix/n_genes.json +++ b/client/__tests__/util/annoMatrix/n_genes.json @@ -1,2640 +1,180 @@ [ - 781, - 1352, - 1131, - 960, - 522, - 782, - 783, - 790, - 533, - 550, - 1116, - 751, - 866, - 1059, - 458, - 335, - 1424, - 1014, - 1446, - 446, - 1020, - 417, - 878, - 789, - 510, - 824, - 1545, - 996, - 937, - 1368, - 428, - 406, - 1020, - 786, - 1019, - 750, - 822, - 982, - 876, - 930, - 838, - 1014, - 732, - 877, - 782, - 787, - 791, - 880, - 801, - 1215, - 343, - 1460, - 1250, - 756, - 836, - 824, - 827, - 1238, - 1243, - 1652, - 843, - 825, - 656, - 776, - 766, - 1465, - 790, - 871, - 803, - 965, - 800, - 876, - 690, - 988, - 906, - 741, - 620, - 867, - 916, - 969, - 803, - 732, - 555, - 790, - 862, - 900, - 674, - 397, - 663, - 563, - 786, - 859, - 568, - 412, - 1043, - 1206, - 702, - 1263, - 929, - 1079, - 938, - 316, - 900, - 919, - 862, - 903, - 390, - 1717, - 819, - 1877, - 660, - 791, - 478, - 769, - 481, - 819, - 866, - 600, - 1185, - 650, - 775, - 699, - 642, - 857, - 832, - 388, - 710, - 341, - 894, - 935, - 604, - 1008, - 985, - 679, - 603, - 864, - 1031, - 887, - 603, - 610, - 1119, - 669, - 794, - 963, - 756, - 637, - 1032, - 776, - 860, - 825, - 852, - 745, - 858, - 925, - 1228, - 806, - 715, - 668, - 779, - 1197, - 888, - 1273, - 873, - 847, - 781, - 959, - 805, - 554, - 604, - 785, - 978, - 910, - 936, - 997, - 961, - 1314, - 799, - 1112, - 677, - 775, - 1298, - 657, - 626, - 1313, - 467, - 936, - 977, - 780, - 1311, - 432, - 579, - 850, - 736, - 800, - 892, - 860, - 720, - 822, - 681, - 954, - 889, - 1265, - 919, - 799, - 833, - 496, - 1476, - 848, - 869, - 1059, - 490, - 897, - 832, - 864, - 419, - 856, - 907, - 791, - 756, - 771, - 957, - 1190, - 680, - 524, - 908, - 506, - 851, - 775, - 793, - 748, - 951, - 643, - 1277, - 828, - 480, - 969, - 1112, - 648, - 805, - 1223, - 1023, - 669, - 489, - 390, - 350, - 1113, - 837, - 1547, - 840, - 581, - 748, - 1861, - 735, - 488, - 1016, - 585, - 797, - 769, - 490, - 1307, - 895, - 686, - 602, - 772, - 704, - 892, - 1169, - 1375, - 1189, - 892, - 2455, - 355, - 1856, - 1317, - 703, - 825, - 736, - 1997, - 892, - 1034, - 545, - 1188, - 659, - 1056, - 819, - 979, - 632, - 598, - 690, - 310, - 803, - 743, - 560, - 1073, - 844, - 882, - 841, - 815, - 771, - 976, - 986, - 820, - 957, - 640, - 1012, - 927, - 794, - 753, - 791, - 366, - 539, - 752, - 769, - 650, - 947, - 771, - 824, - 744, - 837, - 723, - 640, - 923, - 1174, - 1597, - 699, - 618, - 1418, - 820, - 1047, - 981, - 866, - 527, - 762, - 717, - 860, - 603, - 828, - 476, - 1071, - 775, - 614, - 913, - 836, - 669, - 942, - 792, - 871, - 1046, - 859, - 793, - 822, - 751, - 435, - 1142, - 781, - 718, - 471, - 1750, - 892, - 841, - 1156, - 1031, - 912, - 873, - 824, - 1233, - 1312, - 575, - 605, - 717, - 1019, - 1215, - 928, - 1780, - 657, - 718, - 646, - 808, - 1120, - 750, - 390, - 1100, - 456, - 755, - 1118, - 571, - 867, - 728, - 916, - 491, - 960, - 625, - 1090, - 772, - 968, - 480, - 810, - 725, - 1016, - 1011, - 1075, - 808, - 672, - 950, - 862, - 766, - 963, - 507, - 570, - 678, - 768, - 1037, - 885, - 1426, - 1496, - 587, - 879, - 924, - 783, - 696, - 1057, - 783, - 867, - 919, - 1251, - 1023, - 727, - 645, - 1217, - 929, - 792, - 994, - 1025, - 946, - 600, - 881, - 975, - 1609, - 758, - 772, - 682, - 998, - 979, - 1045, - 706, - 808, - 855, - 819, - 1147, - 742, - 914, - 969, - 704, - 1398, - 581, - 809, - 921, - 805, - 542, - 888, - 519, - 1092, - 762, - 698, - 752, - 771, - 899, - 1101, - 760, - 881, - 1124, - 809, - 445, - 1703, - 789, - 641, - 819, - 890, - 767, - 806, - 1323, - 942, - 807, - 981, - 888, - 726, - 1190, - 826, - 661, - 713, - 816, - 822, - 806, - 864, - 464, - 664, - 931, - 860, - 674, - 803, - 464, - 788, - 1068, - 781, - 843, - 779, - 873, - 707, - 492, - 669, - 982, - 749, - 789, - 780, - 561, - 655, - 432, - 801, - 945, - 770, - 503, - 766, - 776, - 970, - 989, - 654, - 762, - 882, - 1236, - 1499, - 626, - 1380, - 1170, - 491, - 833, - 924, - 581, - 842, - 596, - 811, - 542, - 1572, - 758, - 854, - 274, - 1413, - 872, - 559, - 907, - 951, - 1175, - 946, - 905, - 737, - 604, - 843, - 606, - 1079, - 668, - 785, - 726, - 978, - 941, - 994, - 655, - 1013, - 987, - 591, - 1041, - 625, - 582, - 814, - 570, - 775, - 822, - 715, - 738, - 956, - 1178, - 743, - 1861, - 841, - 944, - 783, - 643, - 924, - 936, - 431, - 490, - 532, - 524, - 620, - 749, - 1334, - 834, - 790, - 702, - 892, - 693, - 784, - 944, - 471, - 839, - 529, - 729, - 1084, - 802, - 886, - 815, - 856, - 746, - 1318, - 545, - 696, - 872, - 1154, - 467, - 725, - 1027, - 479, - 728, - 926, - 1282, - 907, - 833, - 1024, - 838, - 900, - 737, - 367, - 459, - 1030, - 1279, - 756, - 662, - 1323, - 1003, - 359, - 770, - 813, - 634, - 924, - 1184, - 901, - 816, - 1421, - 771, - 706, - 953, - 348, - 716, - 870, - 715, - 550, - 689, - 947, - 1157, - 690, - 383, - 374, - 882, - 697, - 246, - 833, - 1006, - 1181, - 974, - 856, - 978, - 1551, - 965, - 907, - 565, - 417, - 907, - 927, - 966, - 658, - 727, - 743, - 381, - 385, - 905, - 645, - 1167, - 936, - 724, - 618, - 1038, - 853, - 808, - 1403, - 762, - 741, - 687, - 932, - 1096, - 601, - 652, - 895, - 682, - 1553, - 604, - 823, - 803, - 646, - 917, - 942, - 850, - 795, - 771, - 949, - 516, - 664, - 1001, - 637, - 619, - 907, - 961, - 812, - 793, - 1043, - 1343, - 1326, - 981, - 675, - 937, - 631, - 1026, - 1135, - 499, - 948, - 801, - 848, - 741, - 604, - 864, - 1076, - 1106, - 1111, - 624, - 1008, - 908, - 815, - 346, - 1062, - 803, - 749, - 779, - 1027, - 1032, - 1040, - 654, - 631, - 755, - 854, - 850, - 798, - 864, - 1078, - 690, - 864, - 1523, - 838, - 966, - 389, - 1654, - 808, - 885, - 1665, - 920, - 855, - 807, - 859, - 1276, - 987, - 1079, - 678, - 626, - 831, - 829, - 1009, - 547, - 893, - 722, - 656, - 415, - 773, - 1262, - 1218, - 365, - 661, - 805, - 1409, - 1094, - 779, - 898, - 830, - 1242, - 864, - 576, - 901, - 1274, - 852, - 1006, - 719, - 763, - 683, - 957, - 831, - 724, - 354, - 763, - 910, - 749, - 626, - 870, - 795, - 1078, - 736, - 835, - 402, - 1203, - 699, - 755, - 697, - 1229, - 637, - 666, - 846, - 1036, - 1027, - 831, - 999, - 942, - 891, - 1007, - 712, - 990, - 725, - 745, - 921, - 333, - 1042, - 895, - 873, - 1612, - 724, - 929, - 601, - 862, - 908, - 658, - 775, - 724, - 753, - 741, - 690, - 379, - 608, - 927, - 777, - 969, - 827, - 709, - 385, - 690, - 769, - 554, - 892, - 761, - 367, - 731, - 1103, - 944, - 832, - 675, - 652, - 418, - 727, - 745, - 872, - 1336, - 863, - 934, - 844, - 721, - 432, - 782, - 1006, - 834, - 840, - 840, - 819, - 699, - 489, - 665, - 576, - 1291, - 1102, - 826, - 880, - 738, - 904, - 686, - 874, - 887, - 873, - 560, - 766, - 710, - 1135, - 1054, - 805, - 724, - 973, - 1201, - 575, - 838, - 865, - 546, - 811, - 884, - 886, - 791, - 1026, - 2000, - 644, - 763, - 969, - 800, - 359, - 624, - 993, - 800, - 1167, - 833, - 1871, - 616, - 822, - 647, - 1000, - 618, - 734, - 618, - 1938, - 861, - 945, - 1032, - 723, - 984, - 994, - 771, - 738, - 1583, - 1113, - 614, - 1146, - 615, - 848, - 983, - 677, - 972, - 791, - 827, - 804, - 395, - 843, - 493, - 741, - 941, - 1659, - 742, - 1517, - 559, - 937, - 740, - 781, - 819, - 813, - 578, - 1022, - 1191, - 824, - 1146, - 757, - 638, - 830, - 713, - 609, - 1271, - 680, - 769, - 1119, - 731, - 804, - 781, - 916, - 735, - 835, - 1257, - 472, - 879, - 851, - 1023, - 661, - 1008, - 748, - 845, - 393, - 675, - 843, - 876, - 939, - 932, - 760, - 735, - 1561, - 752, - 940, - 705, - 405, - 690, - 1071, - 544, - 927, - 817, - 388, - 560, - 1322, - 640, - 886, - 1075, - 689, - 524, - 606, - 802, - 868, - 939, - 753, - 770, - 1105, - 841, - 786, - 445, - 703, - 593, - 875, - 901, - 927, - 798, - 1221, - 415, - 1381, - 949, - 1322, - 1169, - 745, - 727, - 799, - 490, - 767, - 943, - 808, - 926, - 664, - 569, - 843, - 727, - 1222, - 457, - 1515, - 1138, - 1174, - 525, - 878, - 525, - 999, - 778, - 772, - 819, - 1015, - 939, - 856, - 715, - 793, - 837, - 1193, - 764, - 834, - 677, - 625, - 420, - 837, - 874, - 679, - 811, - 546, - 787, - 587, - 821, - 669, - 813, - 780, - 649, - 924, - 1322, - 701, - 792, - 817, - 667, - 804, - 593, - 740, - 1243, - 859, - 685, - 596, - 1193, - 859, - 775, - 947, - 689, - 907, - 734, - 621, - 336, - 922, - 802, - 812, - 941, - 943, - 868, - 947, - 767, - 701, - 692, - 423, - 775, - 500, - 1100, - 812, - 728, - 616, - 928, - 835, - 454, - 812, - 769, - 1058, - 914, - 628, - 649, - 452, - 754, - 1327, - 776, - 670, - 1017, - 599, - 431, - 967, - 1077, - 2033, - 731, - 533, - 926, - 725, - 559, - 870, - 964, - 1341, - 1981, - 1103, - 326, - 428, - 808, - 821, - 554, - 596, - 680, - 1034, - 849, - 566, - 879, - 1091, - 823, - 447, - 1688, - 868, - 1254, - 942, - 462, - 1055, - 852, - 738, - 804, - 775, - 726, - 993, - 1462, - 1007, - 798, - 1036, - 786, - 948, - 743, - 761, - 838, - 1040, - 859, - 867, - 1188, - 846, - 687, - 672, - 629, - 725, - 660, - 809, - 469, - 600, - 812, - 856, - 397, - 786, - 895, - 882, - 449, - 890, - 823, - 1051, - 823, - 1055, - 741, - 999, - 1241, - 790, - 878, - 778, - 1066, - 815, - 465, - 1079, - 743, - 1098, - 807, - 1120, - 1025, - 805, - 676, - 828, - 763, - 997, - 852, - 866, - 1118, - 508, - 928, - 958, - 932, - 892, - 905, - 494, - 710, - 1068, - 795, - 787, - 951, - 720, - 842, - 890, - 1355, - 1005, - 872, - 1185, - 912, - 869, - 894, - 997, - 770, - 554, - 806, - 1426, - 1012, - 452, - 896, - 426, - 239, - 829, - 895, - 787, - 1139, - 925, - 1015, - 1360, - 1097, - 650, - 853, - 549, - 1052, - 307, - 1152, - 907, - 1628, - 731, - 897, - 1749, - 762, - 712, - 1195, - 851, - 864, - 968, - 845, - 331, - 840, - 734, - 948, - 842, - 1543, - 661, - 981, - 912, - 912, - 1063, - 683, - 823, - 996, - 695, - 1483, - 927, - 574, - 1052, - 571, - 1028, - 1263, - 671, - 958, - 747, - 866, - 896, - 489, - 643, - 923, - 820, - 1466, - 550, - 1112, - 1006, - 1448, - 727, - 899, - 998, - 563, - 870, - 903, - 516, - 754, - 879, - 588, - 740, - 798, - 798, - 653, - 902, - 990, - 724, - 953, - 891, - 1437, - 653, - 714, - 956, - 877, - 1012, - 824, - 1077, - 740, - 692, - 1063, - 771, - 808, - 1389, - 1264, - 952, - 816, - 795, - 795, - 760, - 886, - 349, - 868, - 842, - 819, - 626, - 418, - 903, - 838, - 723, - 436, - 1112, - 724, - 1299, - 719, - 843, - 1090, - 696, - 885, - 627, - 809, - 423, - 729, - 853, - 855, - 608, - 627, - 823, - 1063, - 575, - 743, - 1528, - 681, - 544, - 422, - 731, - 920, - 761, - 884, - 982, - 784, - 496, - 573, - 521, - 663, - 794, - 975, - 856, - 978, - 590, - 905, - 695, - 816, - 976, - 816, - 753, - 791, - 858, - 813, - 841, - 1085, - 1692, - 716, - 955, - 1467, - 741, - 296, - 738, - 1573, - 1119, - 918, - 283, - 703, - 842, - 1253, - 676, - 1636, - 1273, - 380, - 799, - 1491, - 878, - 939, - 725, - 1365, - 818, - 719, - 1343, - 905, - 837, - 803, - 990, - 1084, - 976, - 1630, - 795, - 1408, - 771, - 650, - 779, - 648, - 817, - 1127, - 882, - 954, - 830, - 732, - 783, - 756, - 708, - 976, - 718, - 887, - 809, - 795, - 662, - 912, - 1550, - 1509, - 1021, - 1751, - 776, - 910, - 714, - 530, - 846, - 631, - 1152, - 1118, - 755, - 573, - 1176, - 267, - 918, - 1132, - 849, - 938, - 1140, - 909, - 840, - 806, - 904, - 788, - 778, - 715, - 869, - 714, - 883, - 767, - 858, - 788, - 553, - 634, - 1230, - 1131, - 849, - 811, - 827, - 1753, - 713, - 484, - 783, - 722, - 596, - 514, - 372, - 925, - 747, - 840, - 673, - 955, - 796, - 719, - 718, - 857, - 578, - 1063, - 594, - 997, - 1268, - 341, - 388, - 753, - 834, - 593, - 1189, - 911, - 738, - 476, - 816, - 641, - 746, - 635, - 953, - 801, - 326, - 849, - 499, - 865, - 1420, - 487, - 876, - 797, - 981, - 756, - 850, - 1097, - 998, - 829, - 1159, - 955, - 1061, - 696, - 786, - 743, - 1211, - 893, - 491, - 744, - 1447, - 767, - 1050, - 853, - 1118, - 1428, - 555, - 612, - 854, - 789, - 889, - 784, - 712, - 1323, - 921, - 682, - 794, - 846, - 1012, - 839, - 807, - 587, - 881, - 781, - 1010, - 1182, - 1149, - 812, - 607, - 1155, - 714, - 642, - 1088, - 1291, - 1196, - 325, - 804, - 370, - 359, - 855, - 1165, - 836, - 923, - 863, - 1284, - 1011, - 889, - 984, - 512, - 939, - 883, - 697, - 1211, - 362, - 969, - 1135, - 1239, - 580, - 1103, - 975, - 825, - 1170, - 921, - 640, - 1180, - 378, - 982, - 916, - 1122, - 792, - 619, - 750, - 913, - 775, - 661, - 766, - 768, - 675, - 944, - 940, - 761, - 727, - 767, - 873, - 1043, - 850, - 995, - 680, - 595, - 700, - 753, - 736, - 891, - 685, - 780, - 986, - 989, - 830, - 810, - 685, - 784, - 642, - 742, - 961, - 906, - 829, - 621, - 822, - 717, - 1210, - 800, - 1963, - 749, - 757, - 570, - 831, - 721, - 336, - 802, - 1001, - 886, - 631, - 759, - 631, - 550, - 984, - 767, - 835, - 777, - 639, - 860, - 1413, - 747, - 779, - 540, - 367, - 1629, - 1380, - 689, - 1001, - 809, - 337, - 1103, - 796, - 966, - 782, - 1018, - 642, - 967, - 436, - 826, - 779, - 1000, - 601, - 796, - 945, - 1679, - 1123, - 596, - 995, - 720, - 588, - 759, - 452, - 780, - 836, - 515, - 846, - 392, - 283, - 710, - 1158, - 796, - 895, - 585, - 559, - 859, - 879, - 858, - 842, - 643, - 1308, - 595, - 1181, - 909, - 710, - 821, - 817, - 841, - 1197, - 640, - 1425, - 947, - 900, - 852, - 460, - 1100, - 824, - 780, - 932, - 542, - 1137, - 1225, - 997, - 572, - 780, - 765, - 906, - 793, - 753, - 772, - 854, - 936, - 1048, - 819, - 645, - 619, - 314, - 726, - 737, - 1162, - 1081, - 868, - 1032, - 913, - 476, - 490, - 799, - 1201, - 997, - 898, - 212, - 1586, - 427, - 947, - 937, - 724, - 380, - 715, - 739, - 931, - 973, - 773, - 1497, - 906, - 798, - 953, - 471, - 821, - 806, - 714, - 828, - 727, - 773, - 976, - 856, - 727, - 761, - 1084, - 1557, - 693, - 559, - 627, - 795, - 750, - 838, - 803, - 453, - 734, - 607, - 1029, - 805, - 669, - 505, - 858, - 832, - 1019, - 585, - 1225, - 1287, - 903, - 752, - 2020, - 774, - 666, - 843, - 857, - 887, - 1082, - 656, - 674, - 911, - 734, - 910, - 672, - 802, - 539, - 699, - 941, - 828, - 800, - 642, - 733, - 607, - 992, - 379, - 562, - 847, - 787, - 1461, - 732, - 941, - 785, - 696, - 795, - 809, - 828, - 651, - 882, - 972, - 1323, - 679, - 774, - 784, - 766, - 520, - 671, - 796, - 644, - 1549, - 756, - 723, - 788, - 643, - 856, - 825, - 730, - 831, - 653, - 429, - 641, - 637, - 812, - 1527, - 859, - 972, - 744, - 869, - 508, - 624, - 923, - 976, - 801, - 1014, - 1429, - 586, - 692, - 704, - 1176, - 806, - 883, - 1249, - 765, - 743, - 907, - 666, - 669, - 364, - 794, - 959, - 766, - 937, - 1398, - 942, - 1469, - 905, - 812, - 572, - 1378, - 1058, - 1215, - 697, - 531, - 676, - 1819, - 503, - 801, - 943, - 874, - 813, - 694, - 494, - 660, - 1467, - 976, - 833, - 689, - 921, - 625, - 1428, - 817, - 909, - 956, - 765, - 1207, - 829, - 1648, - 554, - 1500, - 953, - 647, - 537, - 786, - 814, - 761, - 862, - 838, - 1102, - 1392, - 1042, - 372, - 971, - 1364, - 1137, - 847, - 935, - 710, - 1070, - 914, - 855, - 759, - 654, - 981, - 1193, - 397, - 1123, - 616, - 747, - 876, - 949, - 965, - 789, - 752, - 717, - 1198, - 952, - 625, - 784, - 914, - 659, - 913, - 863, - 959, - 1637, - 796, - 1508, - 906, - 714, - 1195, - 867, - 819, - 375, - 656, - 1047, - 745, - 866, - 1186, - 1669, - 539, - 942, - 839, - 927, - 796, - 734, - 831, - 967, - 620, - 814, - 605, - 1391, - 655, - 1512, - 625, - 719, - 547, - 864, - 902, - 853, - 1143, - 990, - 858, - 604, - 1291, - 701, - 859, - 768, - 1621, - 715, - 594, - 783, - 1608, - 927, - 740, - 805, - 705, - 491, - 514, - 768, - 880, - 993, - 356, - 748, - 993, - 801, - 843, - 1194, - 794, - 606, - 810, - 882, - 682, - 1126, - 792, - 829, - 1657, - 786, - 610, - 664, - 790, - 852, - 678, - 589, - 930, - 690, - 840, - 647, - 622, - 427, - 856, - 522, - 1262, - 722, - 641, - 997, - 983, - 1099, - 607, - 704, - 947, - 886, - 1062, - 659, - 995, - 492, - 754, - 676, - 837, - 532, - 598, - 1274, - 921, - 700, - 828, - 828, - 543, - 815, - 709, - 842, - 1200, - 1126, - 1327, - 849, - 1160, - 707, - 675, - 709, - 990, - 270, - 445, - 892, - 1040, - 832, - 815, - 437, - 1401, - 1341, - 480, - 1517, - 704, - 622, - 823, - 731, - 781, - 849, - 1209, - 472, - 838, - 643, - 1101, - 879, - 895, - 408, - 832, - 845, - 928, - 920, - 1269, - 652, - 1463, - 840, - 706, - 956, - 1219, - 612, - 970, - 789, - 382, - 533, - 627, - 388, - 655, - 1103, - 782, - 1231, - 617, - 589, - 758, - 882, - 909, - 661, - 558, - 947, - 491, - 1386, - 1481, - 823, - 1064, - 681, - 652, - 363, - 824, - 933, - 611, - 886, - 806, - 531, - 864, - 648, - 1142, - 736, - 955, - 826, - 725, - 1174, - 841, - 1006, - 1418, - 955, - 829, - 1038, - 632, - 750, - 846, - 1033, - 859, - 890, - 893, - 1030, - 913, - 1385, - 750, - 416, - 703, - 522, - 856, - 914, - 742, - 381, - 1079, - 671, - 1101, - 858, - 663, - 581, - 845, - 881, - 823, - 835, - 1290, - 598, - 1130, - 793, - 838, - 765, - 768, - 815, - 810, - 912, - 818, - 790, - 665, - 703, - 875, - 657, - 1567, - 688, - 749, - 1076, - 782, - 543, - 1100, - 841, - 809, - 789, - 1263, - 758, - 368, - 1022, - 730, - 1101, - 478, - 488, - 618, - 940, - 771, - 784, - 847, - 1303, - 821, - 1111, - 752, - 1128, - 958, - 742, - 782, - 824, - 751, - 872, - 939, - 606, - 698, - 705, - 963, - 607, - 621, - 1650, - 1093, - 545, - 670, - 617, - 723, - 1194, - 1019, - 1291, - 758, - 855, - 1549, - 743, - 1372, - 802, - 337, - 1121, - 1028, - 1524, - 645, - 847, - 866, - 941, - 751, - 583, - 796, - 793, - 975, - 936, - 524, - 659, - 607, - 1433, - 562, - 696, - 927, - 517, - 719, - 599, - 639, - 977, - 1019, - 816, - 672, - 1903, - 1162, - 964, - 936, - 947, - 989, - 790, - 902, - 982, - 673, - 856, - 629, - 692, - 843, - 940, - 795, - 780, - 821, - 471, - 702, - 631, - 1557, - 868, - 901, - 798, - 1020, - 885, - 881, - 719, - 1043, - 1238, - 565, - 776, - 696, - 725, - 365, - 811, - 1212, - 1178, - 1132, - 661, - 831, - 786, - 471, - 835, - 564, - 929, - 958, - 706, - 388, - 842, - 965, - 1088, - 511, - 794, - 900, - 865, - 789, - 504, - 701, - 817, - 796, - 972, - 906, - 871, - 922, - 724, - 628, - 1479, - 533, - 1101, - 1913, - 855, - 1266, - 884, - 817, - 619, - 591, - 685, - 887, - 1336, - 656, - 1227, - 980, - 817, - 582, - 1370, - 460, - 638, - 471, - 650, - 414, - 907, - 1147, - 732, - 992, - 801, - 822, - 529, - 737, - 806, - 816, - 889, - 1305, - 588, - 657, - 1154, - 713, - 326, - 1129, - 1603, - 879, - 1156, - 642, - 285, - 825, - 823, - 719, - 1253, - 971, - 853, - 916, - 1053, - 515, - 1017, - 953, - 832, - 645, - 667, - 1326, - 547, - 636, - 1783, - 1211, - 788, - 807, - 1104, - 884, - 848, - 788, - 1013, - 1003, - 916, - 818, - 828, - 882, - 959, - 395, - 368, - 787, - 929, - 1379, - 711, - 733, - 752, - 464, - 626, - 735, - 946, - 876, - 647, - 536, - 954, - 486, - 712, - 786, - 438, - 807, - 1016, - 551, - 841, - 929, - 757, - 971, - 708, - 567, - 881, - 801, - 873, - 805, - 1359, - 866, - 945, - 1068, - 819, - 815, - 1058, - 845, - 881, - 1051, - 1179, - 718, - 657, - 882, - 709, - 754, - 735, - 603, - 944, - 1794, - 712, - 721, - 1097, - 813, - 788, - 917, - 656, - 1104, - 1268, - 1239, - 862, - 739, - 858, - 1066, - 752, - 615, - 721, - 571, - 861, - 933, - 807, - 1082, - 820, - 887, - 850, - 1567, - 803, - 1156, - 721, - 692, - 700, - 458, - 637, - 873, - 1544, - 1155, - 1227, - 622, - 454, - 724 + 781, 1352, 1131, 960, 522, 782, 783, 790, 533, 550, 1116, 751, 866, 1059, 458, + 335, 1424, 1014, 1446, 446, 1020, 417, 878, 789, 510, 824, 1545, 996, 937, + 1368, 428, 406, 1020, 786, 1019, 750, 822, 982, 876, 930, 838, 1014, 732, 877, + 782, 787, 791, 880, 801, 1215, 343, 1460, 1250, 756, 836, 824, 827, 1238, + 1243, 1652, 843, 825, 656, 776, 766, 1465, 790, 871, 803, 965, 800, 876, 690, + 988, 906, 741, 620, 867, 916, 969, 803, 732, 555, 790, 862, 900, 674, 397, + 663, 563, 786, 859, 568, 412, 1043, 1206, 702, 1263, 929, 1079, 938, 316, 900, + 919, 862, 903, 390, 1717, 819, 1877, 660, 791, 478, 769, 481, 819, 866, 600, + 1185, 650, 775, 699, 642, 857, 832, 388, 710, 341, 894, 935, 604, 1008, 985, + 679, 603, 864, 1031, 887, 603, 610, 1119, 669, 794, 963, 756, 637, 1032, 776, + 860, 825, 852, 745, 858, 925, 1228, 806, 715, 668, 779, 1197, 888, 1273, 873, + 847, 781, 959, 805, 554, 604, 785, 978, 910, 936, 997, 961, 1314, 799, 1112, + 677, 775, 1298, 657, 626, 1313, 467, 936, 977, 780, 1311, 432, 579, 850, 736, + 800, 892, 860, 720, 822, 681, 954, 889, 1265, 919, 799, 833, 496, 1476, 848, + 869, 1059, 490, 897, 832, 864, 419, 856, 907, 791, 756, 771, 957, 1190, 680, + 524, 908, 506, 851, 775, 793, 748, 951, 643, 1277, 828, 480, 969, 1112, 648, + 805, 1223, 1023, 669, 489, 390, 350, 1113, 837, 1547, 840, 581, 748, 1861, + 735, 488, 1016, 585, 797, 769, 490, 1307, 895, 686, 602, 772, 704, 892, 1169, + 1375, 1189, 892, 2455, 355, 1856, 1317, 703, 825, 736, 1997, 892, 1034, 545, + 1188, 659, 1056, 819, 979, 632, 598, 690, 310, 803, 743, 560, 1073, 844, 882, + 841, 815, 771, 976, 986, 820, 957, 640, 1012, 927, 794, 753, 791, 366, 539, + 752, 769, 650, 947, 771, 824, 744, 837, 723, 640, 923, 1174, 1597, 699, 618, + 1418, 820, 1047, 981, 866, 527, 762, 717, 860, 603, 828, 476, 1071, 775, 614, + 913, 836, 669, 942, 792, 871, 1046, 859, 793, 822, 751, 435, 1142, 781, 718, + 471, 1750, 892, 841, 1156, 1031, 912, 873, 824, 1233, 1312, 575, 605, 717, + 1019, 1215, 928, 1780, 657, 718, 646, 808, 1120, 750, 390, 1100, 456, 755, + 1118, 571, 867, 728, 916, 491, 960, 625, 1090, 772, 968, 480, 810, 725, 1016, + 1011, 1075, 808, 672, 950, 862, 766, 963, 507, 570, 678, 768, 1037, 885, 1426, + 1496, 587, 879, 924, 783, 696, 1057, 783, 867, 919, 1251, 1023, 727, 645, + 1217, 929, 792, 994, 1025, 946, 600, 881, 975, 1609, 758, 772, 682, 998, 979, + 1045, 706, 808, 855, 819, 1147, 742, 914, 969, 704, 1398, 581, 809, 921, 805, + 542, 888, 519, 1092, 762, 698, 752, 771, 899, 1101, 760, 881, 1124, 809, 445, + 1703, 789, 641, 819, 890, 767, 806, 1323, 942, 807, 981, 888, 726, 1190, 826, + 661, 713, 816, 822, 806, 864, 464, 664, 931, 860, 674, 803, 464, 788, 1068, + 781, 843, 779, 873, 707, 492, 669, 982, 749, 789, 780, 561, 655, 432, 801, + 945, 770, 503, 766, 776, 970, 989, 654, 762, 882, 1236, 1499, 626, 1380, 1170, + 491, 833, 924, 581, 842, 596, 811, 542, 1572, 758, 854, 274, 1413, 872, 559, + 907, 951, 1175, 946, 905, 737, 604, 843, 606, 1079, 668, 785, 726, 978, 941, + 994, 655, 1013, 987, 591, 1041, 625, 582, 814, 570, 775, 822, 715, 738, 956, + 1178, 743, 1861, 841, 944, 783, 643, 924, 936, 431, 490, 532, 524, 620, 749, + 1334, 834, 790, 702, 892, 693, 784, 944, 471, 839, 529, 729, 1084, 802, 886, + 815, 856, 746, 1318, 545, 696, 872, 1154, 467, 725, 1027, 479, 728, 926, 1282, + 907, 833, 1024, 838, 900, 737, 367, 459, 1030, 1279, 756, 662, 1323, 1003, + 359, 770, 813, 634, 924, 1184, 901, 816, 1421, 771, 706, 953, 348, 716, 870, + 715, 550, 689, 947, 1157, 690, 383, 374, 882, 697, 246, 833, 1006, 1181, 974, + 856, 978, 1551, 965, 907, 565, 417, 907, 927, 966, 658, 727, 743, 381, 385, + 905, 645, 1167, 936, 724, 618, 1038, 853, 808, 1403, 762, 741, 687, 932, 1096, + 601, 652, 895, 682, 1553, 604, 823, 803, 646, 917, 942, 850, 795, 771, 949, + 516, 664, 1001, 637, 619, 907, 961, 812, 793, 1043, 1343, 1326, 981, 675, 937, + 631, 1026, 1135, 499, 948, 801, 848, 741, 604, 864, 1076, 1106, 1111, 624, + 1008, 908, 815, 346, 1062, 803, 749, 779, 1027, 1032, 1040, 654, 631, 755, + 854, 850, 798, 864, 1078, 690, 864, 1523, 838, 966, 389, 1654, 808, 885, 1665, + 920, 855, 807, 859, 1276, 987, 1079, 678, 626, 831, 829, 1009, 547, 893, 722, + 656, 415, 773, 1262, 1218, 365, 661, 805, 1409, 1094, 779, 898, 830, 1242, + 864, 576, 901, 1274, 852, 1006, 719, 763, 683, 957, 831, 724, 354, 763, 910, + 749, 626, 870, 795, 1078, 736, 835, 402, 1203, 699, 755, 697, 1229, 637, 666, + 846, 1036, 1027, 831, 999, 942, 891, 1007, 712, 990, 725, 745, 921, 333, 1042, + 895, 873, 1612, 724, 929, 601, 862, 908, 658, 775, 724, 753, 741, 690, 379, + 608, 927, 777, 969, 827, 709, 385, 690, 769, 554, 892, 761, 367, 731, 1103, + 944, 832, 675, 652, 418, 727, 745, 872, 1336, 863, 934, 844, 721, 432, 782, + 1006, 834, 840, 840, 819, 699, 489, 665, 576, 1291, 1102, 826, 880, 738, 904, + 686, 874, 887, 873, 560, 766, 710, 1135, 1054, 805, 724, 973, 1201, 575, 838, + 865, 546, 811, 884, 886, 791, 1026, 2000, 644, 763, 969, 800, 359, 624, 993, + 800, 1167, 833, 1871, 616, 822, 647, 1000, 618, 734, 618, 1938, 861, 945, + 1032, 723, 984, 994, 771, 738, 1583, 1113, 614, 1146, 615, 848, 983, 677, 972, + 791, 827, 804, 395, 843, 493, 741, 941, 1659, 742, 1517, 559, 937, 740, 781, + 819, 813, 578, 1022, 1191, 824, 1146, 757, 638, 830, 713, 609, 1271, 680, 769, + 1119, 731, 804, 781, 916, 735, 835, 1257, 472, 879, 851, 1023, 661, 1008, 748, + 845, 393, 675, 843, 876, 939, 932, 760, 735, 1561, 752, 940, 705, 405, 690, + 1071, 544, 927, 817, 388, 560, 1322, 640, 886, 1075, 689, 524, 606, 802, 868, + 939, 753, 770, 1105, 841, 786, 445, 703, 593, 875, 901, 927, 798, 1221, 415, + 1381, 949, 1322, 1169, 745, 727, 799, 490, 767, 943, 808, 926, 664, 569, 843, + 727, 1222, 457, 1515, 1138, 1174, 525, 878, 525, 999, 778, 772, 819, 1015, + 939, 856, 715, 793, 837, 1193, 764, 834, 677, 625, 420, 837, 874, 679, 811, + 546, 787, 587, 821, 669, 813, 780, 649, 924, 1322, 701, 792, 817, 667, 804, + 593, 740, 1243, 859, 685, 596, 1193, 859, 775, 947, 689, 907, 734, 621, 336, + 922, 802, 812, 941, 943, 868, 947, 767, 701, 692, 423, 775, 500, 1100, 812, + 728, 616, 928, 835, 454, 812, 769, 1058, 914, 628, 649, 452, 754, 1327, 776, + 670, 1017, 599, 431, 967, 1077, 2033, 731, 533, 926, 725, 559, 870, 964, 1341, + 1981, 1103, 326, 428, 808, 821, 554, 596, 680, 1034, 849, 566, 879, 1091, 823, + 447, 1688, 868, 1254, 942, 462, 1055, 852, 738, 804, 775, 726, 993, 1462, + 1007, 798, 1036, 786, 948, 743, 761, 838, 1040, 859, 867, 1188, 846, 687, 672, + 629, 725, 660, 809, 469, 600, 812, 856, 397, 786, 895, 882, 449, 890, 823, + 1051, 823, 1055, 741, 999, 1241, 790, 878, 778, 1066, 815, 465, 1079, 743, + 1098, 807, 1120, 1025, 805, 676, 828, 763, 997, 852, 866, 1118, 508, 928, 958, + 932, 892, 905, 494, 710, 1068, 795, 787, 951, 720, 842, 890, 1355, 1005, 872, + 1185, 912, 869, 894, 997, 770, 554, 806, 1426, 1012, 452, 896, 426, 239, 829, + 895, 787, 1139, 925, 1015, 1360, 1097, 650, 853, 549, 1052, 307, 1152, 907, + 1628, 731, 897, 1749, 762, 712, 1195, 851, 864, 968, 845, 331, 840, 734, 948, + 842, 1543, 661, 981, 912, 912, 1063, 683, 823, 996, 695, 1483, 927, 574, 1052, + 571, 1028, 1263, 671, 958, 747, 866, 896, 489, 643, 923, 820, 1466, 550, 1112, + 1006, 1448, 727, 899, 998, 563, 870, 903, 516, 754, 879, 588, 740, 798, 798, + 653, 902, 990, 724, 953, 891, 1437, 653, 714, 956, 877, 1012, 824, 1077, 740, + 692, 1063, 771, 808, 1389, 1264, 952, 816, 795, 795, 760, 886, 349, 868, 842, + 819, 626, 418, 903, 838, 723, 436, 1112, 724, 1299, 719, 843, 1090, 696, 885, + 627, 809, 423, 729, 853, 855, 608, 627, 823, 1063, 575, 743, 1528, 681, 544, + 422, 731, 920, 761, 884, 982, 784, 496, 573, 521, 663, 794, 975, 856, 978, + 590, 905, 695, 816, 976, 816, 753, 791, 858, 813, 841, 1085, 1692, 716, 955, + 1467, 741, 296, 738, 1573, 1119, 918, 283, 703, 842, 1253, 676, 1636, 1273, + 380, 799, 1491, 878, 939, 725, 1365, 818, 719, 1343, 905, 837, 803, 990, 1084, + 976, 1630, 795, 1408, 771, 650, 779, 648, 817, 1127, 882, 954, 830, 732, 783, + 756, 708, 976, 718, 887, 809, 795, 662, 912, 1550, 1509, 1021, 1751, 776, 910, + 714, 530, 846, 631, 1152, 1118, 755, 573, 1176, 267, 918, 1132, 849, 938, + 1140, 909, 840, 806, 904, 788, 778, 715, 869, 714, 883, 767, 858, 788, 553, + 634, 1230, 1131, 849, 811, 827, 1753, 713, 484, 783, 722, 596, 514, 372, 925, + 747, 840, 673, 955, 796, 719, 718, 857, 578, 1063, 594, 997, 1268, 341, 388, + 753, 834, 593, 1189, 911, 738, 476, 816, 641, 746, 635, 953, 801, 326, 849, + 499, 865, 1420, 487, 876, 797, 981, 756, 850, 1097, 998, 829, 1159, 955, 1061, + 696, 786, 743, 1211, 893, 491, 744, 1447, 767, 1050, 853, 1118, 1428, 555, + 612, 854, 789, 889, 784, 712, 1323, 921, 682, 794, 846, 1012, 839, 807, 587, + 881, 781, 1010, 1182, 1149, 812, 607, 1155, 714, 642, 1088, 1291, 1196, 325, + 804, 370, 359, 855, 1165, 836, 923, 863, 1284, 1011, 889, 984, 512, 939, 883, + 697, 1211, 362, 969, 1135, 1239, 580, 1103, 975, 825, 1170, 921, 640, 1180, + 378, 982, 916, 1122, 792, 619, 750, 913, 775, 661, 766, 768, 675, 944, 940, + 761, 727, 767, 873, 1043, 850, 995, 680, 595, 700, 753, 736, 891, 685, 780, + 986, 989, 830, 810, 685, 784, 642, 742, 961, 906, 829, 621, 822, 717, 1210, + 800, 1963, 749, 757, 570, 831, 721, 336, 802, 1001, 886, 631, 759, 631, 550, + 984, 767, 835, 777, 639, 860, 1413, 747, 779, 540, 367, 1629, 1380, 689, 1001, + 809, 337, 1103, 796, 966, 782, 1018, 642, 967, 436, 826, 779, 1000, 601, 796, + 945, 1679, 1123, 596, 995, 720, 588, 759, 452, 780, 836, 515, 846, 392, 283, + 710, 1158, 796, 895, 585, 559, 859, 879, 858, 842, 643, 1308, 595, 1181, 909, + 710, 821, 817, 841, 1197, 640, 1425, 947, 900, 852, 460, 1100, 824, 780, 932, + 542, 1137, 1225, 997, 572, 780, 765, 906, 793, 753, 772, 854, 936, 1048, 819, + 645, 619, 314, 726, 737, 1162, 1081, 868, 1032, 913, 476, 490, 799, 1201, 997, + 898, 212, 1586, 427, 947, 937, 724, 380, 715, 739, 931, 973, 773, 1497, 906, + 798, 953, 471, 821, 806, 714, 828, 727, 773, 976, 856, 727, 761, 1084, 1557, + 693, 559, 627, 795, 750, 838, 803, 453, 734, 607, 1029, 805, 669, 505, 858, + 832, 1019, 585, 1225, 1287, 903, 752, 2020, 774, 666, 843, 857, 887, 1082, + 656, 674, 911, 734, 910, 672, 802, 539, 699, 941, 828, 800, 642, 733, 607, + 992, 379, 562, 847, 787, 1461, 732, 941, 785, 696, 795, 809, 828, 651, 882, + 972, 1323, 679, 774, 784, 766, 520, 671, 796, 644, 1549, 756, 723, 788, 643, + 856, 825, 730, 831, 653, 429, 641, 637, 812, 1527, 859, 972, 744, 869, 508, + 624, 923, 976, 801, 1014, 1429, 586, 692, 704, 1176, 806, 883, 1249, 765, 743, + 907, 666, 669, 364, 794, 959, 766, 937, 1398, 942, 1469, 905, 812, 572, 1378, + 1058, 1215, 697, 531, 676, 1819, 503, 801, 943, 874, 813, 694, 494, 660, 1467, + 976, 833, 689, 921, 625, 1428, 817, 909, 956, 765, 1207, 829, 1648, 554, 1500, + 953, 647, 537, 786, 814, 761, 862, 838, 1102, 1392, 1042, 372, 971, 1364, + 1137, 847, 935, 710, 1070, 914, 855, 759, 654, 981, 1193, 397, 1123, 616, 747, + 876, 949, 965, 789, 752, 717, 1198, 952, 625, 784, 914, 659, 913, 863, 959, + 1637, 796, 1508, 906, 714, 1195, 867, 819, 375, 656, 1047, 745, 866, 1186, + 1669, 539, 942, 839, 927, 796, 734, 831, 967, 620, 814, 605, 1391, 655, 1512, + 625, 719, 547, 864, 902, 853, 1143, 990, 858, 604, 1291, 701, 859, 768, 1621, + 715, 594, 783, 1608, 927, 740, 805, 705, 491, 514, 768, 880, 993, 356, 748, + 993, 801, 843, 1194, 794, 606, 810, 882, 682, 1126, 792, 829, 1657, 786, 610, + 664, 790, 852, 678, 589, 930, 690, 840, 647, 622, 427, 856, 522, 1262, 722, + 641, 997, 983, 1099, 607, 704, 947, 886, 1062, 659, 995, 492, 754, 676, 837, + 532, 598, 1274, 921, 700, 828, 828, 543, 815, 709, 842, 1200, 1126, 1327, 849, + 1160, 707, 675, 709, 990, 270, 445, 892, 1040, 832, 815, 437, 1401, 1341, 480, + 1517, 704, 622, 823, 731, 781, 849, 1209, 472, 838, 643, 1101, 879, 895, 408, + 832, 845, 928, 920, 1269, 652, 1463, 840, 706, 956, 1219, 612, 970, 789, 382, + 533, 627, 388, 655, 1103, 782, 1231, 617, 589, 758, 882, 909, 661, 558, 947, + 491, 1386, 1481, 823, 1064, 681, 652, 363, 824, 933, 611, 886, 806, 531, 864, + 648, 1142, 736, 955, 826, 725, 1174, 841, 1006, 1418, 955, 829, 1038, 632, + 750, 846, 1033, 859, 890, 893, 1030, 913, 1385, 750, 416, 703, 522, 856, 914, + 742, 381, 1079, 671, 1101, 858, 663, 581, 845, 881, 823, 835, 1290, 598, 1130, + 793, 838, 765, 768, 815, 810, 912, 818, 790, 665, 703, 875, 657, 1567, 688, + 749, 1076, 782, 543, 1100, 841, 809, 789, 1263, 758, 368, 1022, 730, 1101, + 478, 488, 618, 940, 771, 784, 847, 1303, 821, 1111, 752, 1128, 958, 742, 782, + 824, 751, 872, 939, 606, 698, 705, 963, 607, 621, 1650, 1093, 545, 670, 617, + 723, 1194, 1019, 1291, 758, 855, 1549, 743, 1372, 802, 337, 1121, 1028, 1524, + 645, 847, 866, 941, 751, 583, 796, 793, 975, 936, 524, 659, 607, 1433, 562, + 696, 927, 517, 719, 599, 639, 977, 1019, 816, 672, 1903, 1162, 964, 936, 947, + 989, 790, 902, 982, 673, 856, 629, 692, 843, 940, 795, 780, 821, 471, 702, + 631, 1557, 868, 901, 798, 1020, 885, 881, 719, 1043, 1238, 565, 776, 696, 725, + 365, 811, 1212, 1178, 1132, 661, 831, 786, 471, 835, 564, 929, 958, 706, 388, + 842, 965, 1088, 511, 794, 900, 865, 789, 504, 701, 817, 796, 972, 906, 871, + 922, 724, 628, 1479, 533, 1101, 1913, 855, 1266, 884, 817, 619, 591, 685, 887, + 1336, 656, 1227, 980, 817, 582, 1370, 460, 638, 471, 650, 414, 907, 1147, 732, + 992, 801, 822, 529, 737, 806, 816, 889, 1305, 588, 657, 1154, 713, 326, 1129, + 1603, 879, 1156, 642, 285, 825, 823, 719, 1253, 971, 853, 916, 1053, 515, + 1017, 953, 832, 645, 667, 1326, 547, 636, 1783, 1211, 788, 807, 1104, 884, + 848, 788, 1013, 1003, 916, 818, 828, 882, 959, 395, 368, 787, 929, 1379, 711, + 733, 752, 464, 626, 735, 946, 876, 647, 536, 954, 486, 712, 786, 438, 807, + 1016, 551, 841, 929, 757, 971, 708, 567, 881, 801, 873, 805, 1359, 866, 945, + 1068, 819, 815, 1058, 845, 881, 1051, 1179, 718, 657, 882, 709, 754, 735, 603, + 944, 1794, 712, 721, 1097, 813, 788, 917, 656, 1104, 1268, 1239, 862, 739, + 858, 1066, 752, 615, 721, 571, 861, 933, 807, 1082, 820, 887, 850, 1567, 803, + 1156, 721, 692, 700, 458, 637, 873, 1544, 1155, 1227, 622, 454, 724 ] diff --git a/client/__tests__/util/annoMatrix/serverMocks/index.ts b/client/__tests__/util/annoMatrix/serverMocks/index.js similarity index 56% rename from client/__tests__/util/annoMatrix/serverMocks/index.ts rename to client/__tests__/util/annoMatrix/serverMocks/index.js index 525c4ea5..a8ef1285 100644 --- a/client/__tests__/util/annoMatrix/serverMocks/index.ts +++ b/client/__tests__/util/annoMatrix/serverMocks/index.js @@ -1,7 +1,6 @@ export const baseDataURL = "https://a.fake.url/api/v0.2"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -(window as any).CELLXGENE = { +window.CELLXGENE = { API: { prefix: baseDataURL, version: "v0.2/", diff --git a/client/__tests__/util/annoMatrix/serverMocks/routes.js b/client/__tests__/util/annoMatrix/serverMocks/routes.js new file mode 100644 index 00000000..94fbe3f6 --- /dev/null +++ b/client/__tests__/util/annoMatrix/serverMocks/routes.js @@ -0,0 +1,211 @@ +import { schema } from "./schema"; +import { Dataframe, KeyIndex } from "../../../../src/util/dataframe"; +import { encodeMatrixFBS } from "../../../../src/util/stateManager/matrix"; + +const indexedSchema = { + obsByName: Object.fromEntries( + schema.schema.annotations.obs.columns.map((v) => [v.name, v]) ?? [] + ), + varByName: Object.fromEntries( + schema.schema.annotations.var.columns.map((v) => [v.name, v]) ?? [] + ), + embByName: Object.fromEntries( + schema.schema.layout.obs.map((v) => [v.name, v]) ?? [] + ), +}; + +function makeMockColumn(s, length) { + const { type } = s; + switch (type) { + case "int32": + return new Int32Array(length).fill(Math.floor(99 * Math.random())); + + case "string": + return new Array(length).fill("test"); + + case "float32": + return new Float32Array(length).fill(99 * Math.random()); + + case "boolean": + return new Array(length).fill(false); + + case "categorical": + return new Array(length).fill(s.categories[0]); + + default: + throw new Error("unkonwn type"); + } +} + +function getEncodedDataframe(colNames, length, colSchemas) { + const colIndex = new KeyIndex(colNames); + const columns = colSchemas.map((s) => makeMockColumn(s, length)); + const df = new Dataframe([length, colNames.length], columns, null, colIndex); + const body = encodeMatrixFBS(df); + return body; +} + +export function dataframeResponse(colNames, columns) { + const colIndex = new KeyIndex(colNames); + const df = new Dataframe( + [columns[0].length, colNames.length], + columns, + null, + colIndex + ); + const body = encodeMatrixFBS(df); + const headers = new Headers({ + "Content-Type": "application/octet-stream", + }); + return () => Promise.resolve({ body, init: { status: 200, headers } }); +} + +function annotationObsResponse(request) { + const url = new URL(request.url); + const params = Array.from(url.searchParams.entries()); + const names = params + .filter(([k]) => k === "annotation-name") + .map(([, v]) => v); + if (!names.every((n) => indexedSchema.obsByName[n])) { + return Promise.reject(new Error("bad obs annotation name in URL")); + } + const colSchemas = names.map((n) => indexedSchema.obsByName[n]); + const body = getEncodedDataframe( + names, + schema.schema.dataframe.nObs, + colSchemas + ); + + const headers = new Headers({ + "Content-Type": "application/octet-stream", + }); + return Promise.resolve({ + body, + init: { status: 200, headers }, + }); +} + +function annotationVarResponse(request) { + const url = new URL(request.url); + const params = Array.from(url.searchParams.entries()); + const names = params + .filter(([k]) => k === "annotation-name") + .map(([, v]) => v); + if (!names.every((n) => indexedSchema.varByName[n])) { + return Promise.reject(new Error("bad var annotation name in URL")); + } + const colSchemas = names.map((n) => indexedSchema.varByName[n]); + const body = getEncodedDataframe( + names, + schema.schema.dataframe.nVar, + colSchemas + ); + + const headers = new Headers({ + "Content-Type": "application/octet-stream", + }); + return Promise.resolve({ + body, + init: { status: 200, headers }, + }); +} + +function layoutObsResponse(request) { + const url = new URL(request.url); + const params = Array.from(url.searchParams.entries()); + const names = params.filter(([k]) => k === "layout-name").map(([, v]) => v); + if (!names.every((n) => indexedSchema.embByName[n])) { + return Promise.reject(new Error("bad layout name in URL")); + } + const dims = names.map((n) => indexedSchema.embByName[n].dims).flat(); + const colSchemas = names + .map((n) => [indexedSchema.embByName[n], indexedSchema.embByName[n]]) + .flat(); + const body = getEncodedDataframe( + dims, + schema.schema.dataframe.nObs, + colSchemas + ); + + const headers = new Headers({ + "Content-Type": "application/octet-stream", + }); + return Promise.resolve({ + body, + init: { status: 200, headers }, + }); +} + +function dataVarResponse(request) { + const url = new URL(request.url); + const params = Array.from(url.searchParams.entries()); + + const colNames = params.map((v) => `${v[0]}/${v[1]}`); + const colSchemas = colNames.map(() => schema.schema.dataframe); + const body = getEncodedDataframe( + colNames, + schema.schema.dataframe.nObs, + colSchemas + ); + + const headers = new Headers({ + "Content-Type": "application/octet-stream", + }); + return Promise.resolve({ + body, + init: { status: 200, headers }, + }); +} + +export function responder(request) { + const url = new URL(request.url); + const { pathname } = url; + if (pathname.endsWith("/annotations/obs")) { + return annotationObsResponse(request); + } + if (pathname.endsWith("/annotations/var")) { + return annotationVarResponse(request); + } + if (pathname.endsWith("/layout/obs")) { + return layoutObsResponse(request); + } + if (pathname.endsWith("/data/var")) { + return dataVarResponse(request); + } + return Promise.reject(new Error("bad URL")); +} + +export function withExpected(expectedURL, expectedParams) { + /* + Do some additional error checking + */ + return (request) => { + // if URL is bogus, reject the promise + const url = new URL(request.url); + if (!url.pathname.endsWith(expectedURL)) { + return Promise.reject(new Error("Unexpected URL!")); + } + const params = Array.from(url.searchParams.entries()).sort( + (a, b) => a[0] < b[0] + ); + expectedParams = expectedParams.slice().sort((a, b) => a[0] < b[0]); + + if ( + params.length !== expectedParams.length || + !params.every( + (p, i) => p[0] === expectedParams[i][0] && p[1] === expectedParams[i][1] + ) + ) { + return Promise.reject(new Error("unexpected name requested in URL")); + } + + return responder(request); + }; +} + +export function annotationsObs(names) { + return withExpected( + "/annotations/obs", + names.map((name) => ["annotation-name", name]) + ); +} diff --git a/client/__tests__/util/annoMatrix/serverMocks/routes.ts b/client/__tests__/util/annoMatrix/serverMocks/routes.ts deleted file mode 100644 index 6c61ac06..00000000 --- a/client/__tests__/util/annoMatrix/serverMocks/routes.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { schema } from "./schema"; -import { Dataframe, KeyIndex } from "../../../../src/util/dataframe"; -import { encodeMatrixFBS } from "../../../../src/util/stateManager/matrix"; - -const indexedSchema = { - obsByName: Object.fromEntries( - schema.schema.annotations.obs.columns.map((v) => [v.name, v]) ?? [] - ), - varByName: Object.fromEntries( - schema.schema.annotations.var.columns.map((v) => [v.name, v]) ?? [] - ), - embByName: Object.fromEntries( - schema.schema.layout.obs.map((v) => [v.name, v]) ?? [] - ), -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function makeMockColumn(s: any, length: any) { - const { type } = s; - switch (type) { - case "int32": - return new Int32Array(length).fill(Math.floor(99 * Math.random())); - - case "string": - return new Array(length).fill("test"); - - case "float32": - return new Float32Array(length).fill(99 * Math.random()); - - case "boolean": - return new Array(length).fill(false); - - case "categorical": - return new Array(length).fill(s.categories[0]); - - default: - throw new Error("unknown type"); - } -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function getEncodedDataframe(colNames: any, length: any, colSchemas: any) { - const colIndex = new KeyIndex(colNames); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const columns = colSchemas.map((s: any) => makeMockColumn(s, length)); - const df = new Dataframe([length, colNames.length], columns, null, colIndex); - const body = encodeMatrixFBS(df); - return body; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function dataframeResponse(colNames: any, columns: any) { - const colIndex = new KeyIndex(colNames); - const df = new Dataframe( - [columns[0].length, colNames.length], - columns, - null, - colIndex - ); - const body = encodeMatrixFBS(df); - const headers = new Headers({ - "Content-Type": "application/octet-stream", - }); - return () => Promise.resolve({ body, init: { status: 200, headers } }); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function annotationObsResponse(request: any) { - const url = new URL(request.url); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const params = Array.from((url.searchParams as any).entries()); - const names = params - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - .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); - // @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type. - if (!names.every((n) => indexedSchema.obsByName[n])) { - 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 body = getEncodedDataframe( - names, - schema.schema.dataframe.nObs, - colSchemas - ); - - const headers = new Headers({ - "Content-Type": "application/octet-stream", - }); - return Promise.resolve({ - body, - init: { status: 200, headers }, - }); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function annotationVarResponse(request: any) { - const url = new URL(request.url); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const params = Array.from((url.searchParams as any).entries()); - const names = params - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - .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); - // @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type. - if (!names.every((n) => indexedSchema.varByName[n])) { - 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 body = getEncodedDataframe( - names, - schema.schema.dataframe.nVar, - colSchemas - ); - - const headers = new Headers({ - "Content-Type": "application/octet-stream", - }); - return Promise.resolve({ - body, - init: { status: 200, headers }, - }); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function layoutObsResponse(request: any) { - const url = new URL(request.url); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - 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); - // @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type. - if (!names.every((n) => indexedSchema.embByName[n])) { - 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 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]]) - .flat(); - const body = getEncodedDataframe( - dims, - schema.schema.dataframe.nObs, - colSchemas - ); - - const headers = new Headers({ - "Content-Type": "application/octet-stream", - }); - return Promise.resolve({ - body, - init: { status: 200, headers }, - }); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function dataVarResponse(request: any) { - const url = new URL(request.url); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const params = Array.from((url.searchParams as any).entries()); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const colNames = params.map((v) => `${(v as any)[0]}/${(v as any)[1]}`); - const colSchemas = colNames.map(() => schema.schema.dataframe); - const body = getEncodedDataframe( - colNames, - schema.schema.dataframe.nObs, - colSchemas - ); - - const headers = new Headers({ - "Content-Type": "application/octet-stream", - }); - return Promise.resolve({ - body, - init: { status: 200, headers }, - }); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function responder(request: any) { - const url = new URL(request.url); - const { pathname } = url; - if (pathname.endsWith("/annotations/obs")) { - return annotationObsResponse(request); - } - if (pathname.endsWith("/annotations/var")) { - return annotationVarResponse(request); - } - if (pathname.endsWith("/layout/obs")) { - return layoutObsResponse(request); - } - if (pathname.endsWith("/data/var")) { - return dataVarResponse(request); - } - return Promise.reject(new Error("bad URL")); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function withExpected(expectedURL: any, expectedParams: any) { - /* - Do some additional error checking - */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - return (request: any) => { - // if URL is bogus, reject the promise - const url = new URL(request.url); - if (!url.pathname.endsWith(expectedURL)) { - return Promise.reject(new Error("Unexpected URL!")); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const params = Array.from((url.searchParams as any).entries()).sort( - // @ts-expect-error ts-migrate(2345) FIXME: Argument of type '(a: unknown, b: unknown) => bool... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (a, b) => (a as any)[0] < (b as any)[0] - ); - expectedParams = expectedParams - .slice() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .sort((a: any, b: any) => a[0] < b[0]); - - if ( - params.length !== expectedParams.length || - !params.every( - (p, i) => - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (p as any)[0] === expectedParams[i][0] && // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (p as any)[1] === expectedParams[i][1] - ) - ) { - return Promise.reject(new Error("unexpected name requested in URL")); - } - - return responder(request); - }; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function annotationsObs(names: any) { - return withExpected( - "/annotations/obs", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - names.map((name: any) => ["annotation-name", name]) - ); -} diff --git a/client/__tests__/util/annoMatrix/serverMocks/schema.ts b/client/__tests__/util/annoMatrix/serverMocks/schema.js similarity index 93% rename from client/__tests__/util/annoMatrix/serverMocks/schema.ts rename to client/__tests__/util/annoMatrix/serverMocks/schema.js index 2bdb63d5..fe995b05 100644 --- a/client/__tests__/util/annoMatrix/serverMocks/schema.ts +++ b/client/__tests__/util/annoMatrix/serverMocks/schema.js @@ -1,6 +1,4 @@ -import { RawSchema } from "../../../../src/common/types/schema"; - -export const schema: { schema: RawSchema } = { +export const schema = { schema: { annotations: { obs: { diff --git a/client/__tests__/util/annoMatrix/umap.json b/client/__tests__/util/annoMatrix/umap.json index 5d7134da..8cd62196 100644 --- a/client/__tests__/util/annoMatrix/umap.json +++ b/client/__tests__/util/annoMatrix/umap.json @@ -1,5282 +1,1698 @@ [ [ - 1.35285573560809, - -0.47802448287846216, - 2.165888749165179, - -8.69549315663449, - 2.0652175331122584, - 0.49520189144034144, - 1.051380238311061, - 1.8418954223210249, - 2.0126272839211943, - -8.406228786835502, - -0.7475822029589808, - 1.0398710174106818, - 2.4614340402375072, - -7.780092250827048, - 2.121988331057579, - 2.8140497988665834, - -9.117412304441292, - 0.7443418440268849, - -0.12612876310385598, - 1.1799221119905499, - -0.6887250690467789, - 3.0125133545646734, - -7.143523307396688, - 0.49794596192762824, - 2.1879318296159007, - -0.04074260948831929, - -1.6304621183653067, - 0.9185120650755632, - 3.330950131646921, - -8.249406782019472, - 2.9837694164624335, - 0.6013868697229028, - -7.973320868544591, - 1.2557275472097205, - -9.037432741704768, - 0.5272899942439975, - -7.3620383459740015, - -8.710739809962973, - 0.04565450184186127, - 0.9995702400422025, - 1.3707704392248314, - 0.4646969234541549, - 3.6660903522856345, - 1.5514822021133166, - 1.8014230367905788, - 0.8562655175966818, - 2.528521602131749, - -8.054206350208998, - 0.6986495744500447, - -8.360293645270179, - -7.028788335956598, - -8.117341523020128, - -8.975178374370575, - -0.12287461935615306, - 0.14568919159482138, - -0.22935322444119527, - -7.197623936888145, - 0.13018576439615953, - -8.262411494404354, - -9.10852755735242, - 0.7589399187829838, - 1.8111041361908446, - 2.0805181051825774, - -8.016584746538891, - 3.1365046821015947, - -8.174435180354182, - 1.8663362319091807, - 3.1219524797361493, - 0.6892426837009439, - 2.244499608696403, - 1.5623054194259811, - 2.3384273670301057, - 0.5378190418426231, - 2.7951515340684123, - -0.5755601568500485, - -0.5065756491480748, - 2.92485140197707, - 1.488221487102054, - 2.209257327297217, - -8.149923929399492, - -8.283361558328565, - 1.2593016566196622, - -7.614791259843514, - 2.0060290322527274, - -7.1957257296755675, - -0.6153994129631802, - 0.647621585176719, - 3.825122324575844, - -0.617206942026205, - -0.0723953060051589, - 2.7502344438270008, - -8.316773079712256, - -0.12703127087171923, - 0.032541047575098556, - -8.366227754298668, - -6.412773785556261, - 1.3622057178832003, - -7.233870565183863, - -7.394245052883867, - -4.525292336025702, - 2.10907364705061, - -7.274801711351849, - 0.4465992849099335, - 3.4309033386585783, - 1.9395204719917993, - 0.023946918636043358, - 2.833582913855396, - -0.3272931840397848, - 0.5946590476457169, - -4.118204094213762, - -8.85541744506898, - 2.4091434789774158, - 3.6121360006509553, - 2.574694350221088, - -8.386406382028346, - -8.087563939058514, - 0.4934831447839657, - 0.9560922248955092, - -9.01149783933102, - 0.8918896398008918, - 2.2792529871367955, - -6.807368181855979, - -0.016013842245326707, - 1.1749914467666223, - 0.5240606442534225, - 3.5680691256852217, - -7.131107288833797, - 0.5345528022913716, - 2.2504990630744834, - 0.43808793952614933, - 0.7054144783650844, - 0.010596177968814935, - -0.44663998860576865, - 2.365041933566587, - 0.8319562986581416, - -8.069079321353989, - 0.3509974873712663, - 1.997283773551994, - 2.4671002696984927, - 1.2639763865572942, - 0.5352041836925608, - 1.8841680192540224, - 2.905270971072112, - 0.1267833933956664, - 2.1242670578822405, - 2.6031580899982645, - -0.4312188043186363, - 0.9370138686596056, - -8.613621000724036, - 3.401549960736509, - 2.2160376306817655, - 0.9212426942869542, - 2.7430630793423205, - -0.5279990283280503, - -8.705539904925752, - 2.4868955732930313, - 1.9190472369020852, - 2.6080540180978486, - 3.2231396825311593, - -9.276648677138272, - 0.30053384369225394, - -5.1928361913065695, - 0.7561482591752087, - -7.571335606375206, - 1.046280867035641, - 0.1068853107329791, - 0.017020521216728503, - 1.8023357156616873, - 2.3724127779605406, - 0.9466561207261283, - 1.110832640530842, - 0.4122690719532064, - 2.5583580087383386, - -7.3448006321193695, - 2.7344695021869314, - -4.7003697238665945, - 0.20345204016224966, - 0.629245474557074, - 0.9436280743194153, - 0.1950924896942039, - -8.39321990754313, - 1.2933036946172936, - 0.7299735362981703, - -8.126373566878598, - -7.3662003803191425, - 1.6881029482355105, - 1.3907142000183166, - 2.5272762201075922, - -6.930322251680463, - 3.0775809978141795, - -0.07918514822520616, - 2.953742730539597, - -0.0017677535678961968, - 2.1886055501621033, - 1.7453622702042706, - 1.4951683077935347, - 1.9836262513675331, - 2.501592487882715, - 1.889625190366337, - 0.7353185031725933, - -6.550417322255917, - 0.7162273209727067, - 1.991404254201194, - -0.37267481858485996, - 0.5938391769786189, - -7.411420218588439, - -8.212939911852136, - 1.7480198752263079, - 1.370594139234737, - 2.6366163782948586, - 4.02933338975498, - 2.0320398581703496, - 1.6817961799238048, - 0.8887318601823143, - 1.8216291886789278, - -8.027511231072134, - -8.486856587037046, - 2.735438151582886, - 0.4550883264617053, - 3.3275023814892997, - 1.914579541768007, - -6.3584026650996535, - 0.8204178209761795, - 1.3315424166556709, - 1.3732448825623564, - 0.9586113508612994, - 1.2104802142030255, - 1.1705199569069644, - 3.2612705045348678, - 1.0492599729227439, - 1.3956439354853487, - -0.026480386394438813, - -8.989715611105217, - 0.8107151133592344, - -7.903104872958988, - 0.5039574785355939, - 2.4828705420315065, - 2.4115742227072956, - 2.8268743166688304, - -8.105979455165985, - 1.8751676391425214, - 0.47027295054406565, - -7.137759512944296, - 2.778992280455717, - -6.954649903722504, - -8.99402332832767, - 1.737009099149306, - -6.436508767115393, - 0.09142569258522178, - 1.4447896979783696, - 3.4407425738326562, - -2.6245975457760076, - 2.7538737258437753, - 1.4538389571409434, - -8.714958685582125, - -7.441383816313331, - 0.7510754908666685, - 0.3637562228618128, - 0.8399532151071638, - -8.08883603972419, - 1.6310142994433159, - 0.6705970298646083, - 2.1442899819450436, - 0.556478231632356, - -7.145388982529729, - 3.0647569182319536, - -8.977111424649609, - -7.711063727771787, - -8.833675637290202, - 2.1741483255925496, - -6.835536842196359, - 3.445543676407967, - -0.5822709787922326, - -8.080212990395578, - 0.713903340693877, - 0.40152969027500107, - 1.036963501913817, - -3.9835806018617936, - 1.4744144211922672, - 0.411592050621132, - 0.9364087576033505, - 0.1137082665706626, - 0.7301752132908366, - -8.266130955066824, - 0.2735006004760863, - 2.184378247744145, - 2.354302848998888, - 2.5485981453437163, - 1.2137100558133114, - -7.247752798634288, - -8.43194359917085, - 3.383507975280563, - 2.2450433484087418, - -9.051751477158193, - 2.8161048993789337, - -0.4262984388451197, - 2.464041660712454, - 1.994465005190346, - 0.22374471688588723, - 2.643110468109436, - 2.0702070585902668, - -7.581863095749053, - -7.512666918910498, - 0.6128565944808063, - 0.3835269276924121, - 1.6392539494894134, - 0.8320845595954978, - 1.5106365905385972, - 1.7720586658631, - 1.0291963010592182, - 1.6418052848350662, - -7.188246151127988, - 0.09198371062898206, - 0.5215544251331047, - 0.6371849805552529, - 3.1589727819067033, - 1.268813153780352, - 0.16681320384399848, - 2.1280869821189468, - -9.082202106655455, - 3.3172849637356663, - -6.590274113813707, - -9.111097213275565, - 1.8592883936797295, - -5.673139437865187, - 0.2980193119458896, - -4.389165578227743, - 1.8052387859523857, - -7.713983531304735, - 2.2016552664769455, - 3.3577319679959863, - 2.7035250626548364, - 2.8625973320310107, - 2.219272719282033, - 2.0324556166791155, - -7.081447243116417, - 1.9937689198645958, - 0.9748403495325826, - -8.927681326460663, - 1.3041703425278484, - 1.82168902095041, - -6.571880276673609, - 2.1953614271043365, - 1.3750668155272605, - 1.512305343143351, - 2.1735048519170364, - 1.2434736921614349, - 2.245753919843488, - 1.0011469888166296, - 1.5077489169341487, - 2.861366444731574, - -0.12975319864357043, - -7.759798128516371, - 1.0486401152193379, - -8.567409130119385, - -8.776709766409404, - 2.0523959720629676, - 0.9702463176224747, - 1.2464262446181968, - 1.2126888337289463, - -9.064260688467613, - 0.2681989849780224, - 2.0648972895331412, - 2.0441326659108716, - 3.0831011651576077, - 2.830334712439813, - 0.08059882892829817, - -7.234692017738882, - 0.6632578036213854, - 1.7306600879590341, - -4.864581457973878, - -9.091852992643224, - 0.07669833990740652, - 0.02245052822235808, - 2.8223097687713388, - 0.6186772967822212, - 0.5475132602144684, - 0.09821139171848503, - -7.1523470860208445, - 2.6794128585643873, - -7.894703748856715, - -7.997464605281789, - 1.9629575179131227, - 1.1035892676473205, - -8.637887747398574, - 1.2205319340415708, - -0.2938745402049933, - -7.00559485207825, - 2.818656762828998, - 1.3729772425199083, - 0.8097641508866747, - 0.8410347707617063, - 1.0747633751558396, - 2.773461678987149, - 0.3807626926184541, - 1.959034468961967, - 2.050909653235062, - -7.630535795118942, - -8.455389050665026, - -0.13534377253691748, - 1.0909180055505898, - 2.2125493767531754, - 0.05717055980198288, - -5.835409235490379, - -8.907589902674092, - 0.6672827627892893, - -0.49655582121382663, - 1.1645365854688123, - 1.034959444203318, - -0.4064455989921577, - -8.907457084740749, - 0.09626630962876037, - -0.30648636877226526, - -8.087071864621759, - -8.984939584746886, - 3.254164419936194, - 0.7377131144975152, - 0.12653586552659382, - 1.5657379656562431, - 0.16448804787290544, - 2.5266905700100337, - 0.20972239604758247, - 1.137118048499744, - 2.7570215436697003, - -8.655373197480369, - -8.228388519208059, - -0.5078345067119657, - 1.5229586758713414, - -7.971332052123057, - 1.6870682706355173, - -7.545705194606324, - -6.862974180738561, - 2.0236854098282038, - 0.33415671891411824, - 1.7267148126287122, - 2.698653301230399, - 2.8048534205439735, - -4.087625024003784, - 0.16022206804150776, - 2.841513133217909, - -0.5047976304668866, - -7.263502458048841, - 1.123338299216964, - -7.710038123638572, - 2.0799806194502155, - -8.73419889042598, - 0.6330292914853181, - 2.1243368489395085, - -0.43313493099211564, - 1.1823642197137227, - -0.42859023726553575, - -0.5091823498451181, - 1.9973258492370753, - -8.38836915444216, - 0.7375029392148328, - 2.1736812780490955, - 1.738419181698482, - 1.6883070352583138, - 0.5537049352527356, - 2.6506657614629896, - 2.8142428026527817, - 1.2235332414634719, - 3.397442150460223, - 1.030353665351954, - 1.3116442758866809, - 1.6452859224830017, - 0.5011618044043213, - -9.088557246507733, - -0.01240447994027973, - 2.581084952945822, - -8.463302117338767, - 0.7118590055640489, - -8.130625360247175, - 1.0834207438804553, - 2.640358178533733, - 0.5653084044265729, - 2.6702250700203165, - 1.6468270224796138, - 0.846414266068259, - 3.1615434834361, - -7.691410230354492, - 1.2557341558261315, - 0.20992282186654185, - 2.477869816844542, - 0.3771536857972718, - 1.9971442195608315, - 0.12915305927423792, - 3.2829579226358123, - 0.07537013445606805, - 2.3092976438959476, - 0.2329424582448878, - 0.8357888209020299, - 1.2180893842173306, - 0.04856351346397796, - 3.5744979379043267, - 1.669535155953666, - 2.3207366356258663, - 0.32681234021190014, - 1.5151106657587101, - 1.8281001077630386, - 3.831754713753577, - 0.8185537560162401, - -5.962281540225824, - 0.9255740617320212, - 0.7820050943170265, - -7.9288721156215605, - 1.0142181524892333, - -7.707662624985399, - 0.6503250943985074, - 1.380100923803612, - -8.05200622560956, - 1.6043286625304296, - 0.8451562069463898, - 0.943690736995706, - -6.704163983926268, - -7.651675754191798, - 2.8069842371494023, - 2.9804034094200733, - 2.512406670381577, - 1.6303008295865888, - 1.2743826657141013, - 2.968429649588173, - 0.07981202025095484, - 0.4659555505286844, - 2.4135861375911265, - 0.3470879379696273, - 2.096925716384769, - 1.7104732337010358, - -8.93244670648019, - -9.054077418131602, - 3.3272023035340923, - 1.9533029770509784, - -0.3578635861118119, - 1.7387635157985106, - 1.0622233414382256, - 1.166330984649243, - 2.290374493758918, - 1.6007386358604836, - 0.4069471299462136, - 3.183141909139203, - -8.289505399777722, - -8.735818891934889, - 1.1927270785407693, - 0.8117335091610367, - -6.839778391731439, - -8.560621059700626, - 3.2327524190054517, - 0.2351280054174659, - -8.069124435396784, - 1.5934052451891958, - -8.016886503130472, - 2.5166474443118187, - 1.8077703556852782, - -6.89917040548509, - 2.331295274393149, - 0.028341084904075293, - 2.45294414025638, - 2.4982955100934663, - 2.6528746304421698, - 0.86949660097944, - 2.9663214606223556, - -0.3283375313402265, - -0.38263116649533446, - -8.617634243641117, - 0.9891606519058725, - 0.11258801303709674, - 2.5995061442041325, - 1.1101383528502828, - 1.7915850107514966, - -0.39955038419449096, - -8.952822233799061, - 0.4338327371453445, - 1.5069996136757637, - 2.2547717788501167, - 2.7922905917041314, - -6.966528492028682, - 0.2707484789662109, - -8.526624100991679, - -4.546150834872335, - 1.968289743381796, - -4.085814940218094, - -8.75651859188767, - 1.0492010807174819, - -8.467274974407134, - 1.593124734813376, - 0.3481380884273988, - -0.15583301716388614, - -6.592603378805345, - -7.117952854897646, - 0.6178371906010927, - 0.9282037231419841, - -7.644178100661795, - -6.847530121470798, - -8.612602760529702, - 1.9615040056293946, - 1.0813198807975406, - -0.07916973209749419, - 0.22878581671923293, - 1.5852329652618449, - 2.6568979004682602, - -8.247382625035774, - -7.31905533769166, - 1.7230334499316773, - 2.1442150754629377, - -0.3913867311853231, - -8.565731523795018, - 0.48836673876161385, - -8.550981123529034, - 2.0765156901835993, - 1.1791232493554893, - 0.4628133554809247, - -8.570612481576456, - 0.31743916249521, - 1.3689304528387372, - 0.9202159446125323, - -0.2270501708321309, - -6.940721954427759, - -7.061116366059591, - -0.2987105617995114, - 3.283450614839531, - 2.1621752246384274, - -8.016471862737987, - -8.167882170647548, - 3.0123025587277055, - -0.12776957890467389, - 0.6576203647895076, - 1.2206369385103255, - 1.7771949646291936, - 0.870129676006453, - -6.896514945865017, - 2.72395569606518, - -0.708821266359798, - -8.178817525909968, - 2.599012631508349, - -7.4413028157194345, - -8.860103070305422, - 3.0123938603834906, - 0.6840626894874334, - 0.10459117875634981, - -0.3227860929645202, - -0.11296946986870815, - 1.8379339717420056, - -7.758420382491858, - 0.2711735110428051, - 3.008850738872426, - -8.328873089908148, - -0.6434888208653092, - 1.381037343424551, - 0.4312276140533374, - 0.5825181663460871, - -6.970927901949955, - 2.0695117930134517, - 0.6152340280892129, - 3.49595199368453, - 0.6938727172986299, - 1.4475996148194237, - -8.609142018851355, - -7.7772768844184315, - -7.544894885797945, - -6.908331226910449, - 0.9089285567242396, - 0.9387047714748711, - 3.7148527852348368, - -7.2476532791433765, - -8.998549396936156, - -6.595387338748019, - 1.438191259922225, - 2.288214765306113, - -0.014760414413903546, - -7.770974287483711, - 0.6453677444470884, - 2.087141400809658, - -8.01699871457284, - 2.400436142220324, - 0.9203163748065302, - 2.9250246221734177, - 1.739337623547591, - 1.0263075400063275, - 1.2133803601560305, - 0.8477548670296504, - 0.2776668814036649, - 1.476863079748618, - 2.38986676603255, - 0.8190010540303145, - -8.600849114974137, - 2.466931763065777, - 0.6942828631671454, - -0.48472949679486216, - 1.3690461720825393, - 1.1386794631201784, - 2.3000790452898423, - -0.5737801992789094, - 1.4894503198246298, - 2.20744903509327, - 2.346612854012468, - 1.9262174442593494, - -8.518158953023475, - 1.2307221290531465, - 2.1206736732011553, - 0.4899710406891571, - 3.1006385409976778, - -7.521213500124812, - 0.5237439927790518, - 1.1519603194807617, - 1.6256078327550763, - -8.914362686096426, - -7.845587362754366, - -8.485506628202467, - 1.9268753736882878, - 1.3412107413635537, - 1.7626357558833163, - -0.3848726650847515, - 2.0535608777636822, - 0.6386486562532143, - 2.1668214225250875, - 1.7621364606735226, - 0.144604733364891, - 3.2287546365823094, - 2.1172647727359086, - 3.2498858720172166, - 2.910690182828211, - 0.5560038424597556, - -5.053249259330138, - 0.1267741317413434, - -7.7520600294259765, - 3.0099939457558884, - 2.530862687511373, - -7.569045043727168, - 3.100572766345718, - -7.598035533924212, - 3.0812254019580134, - 2.665871025642842, - -7.783751872917371, - 0.7792923984254838, - 0.13550411979575336, - 1.9555605803234042, - 2.8109919605641784, - 1.4302939303354323, - -7.077889093884513, - -8.81451549884432, - 1.7948047097881592, - 1.3136659105045494, - -0.05431808661282797, - 2.1745446641766275, - -6.744529238152495, - -7.639481164896453, - 1.9508598546238556, - 2.994506265077541, - -8.047126695755605, - -7.9055428000056445, - -6.880506675107962, - 1.2064549161519937, - 2.40303126836893, - 3.721222591763574, - 1.0392622357574917, - 0.989513670148371, - 1.111295715578283, - 1.5197712593885788, - -0.003830666980349542, - -8.871502646042059, - -7.710228767479039, - 1.316567130437144, - -8.153346603694768, - -0.3065364380133689, - 1.1701046228289196, - 1.4383032441394334, - -5.3338371145364105, - -0.4210221997984218, - 1.6444079959956204, - -8.877769334741437, - 3.103492802343518, - 1.516321164532454, - 0.04550566552419573, - 2.0988285005728082, - -8.805073663059847, - 2.238823922089626, - -7.760574953561919, - 1.7399929534231842, - -6.362716239042421, - 1.342770941232623, - 0.2942419947671681, - 2.460133192304222, - 3.1160109542981256, - -7.863404589522134, - 1.339783928604639, - 3.1828691359625, - -7.419356727249834, - 0.7064775403365423, - -0.30887312014924456, - -8.456035013610844, - -6.53454968512149, - 2.178316715644698, - 1.6842159505158856, - -9.021975554572357, - -7.507648493713097, - 3.202200540495128, - -8.100426309998456, - 0.9594422746731098, - -8.845494271765292, - 1.175056685814502, - 0.04214137587627019, - -0.5673660022469825, - -9.20656186730306, - 2.973187278981339, - 0.5737719406547798, - 1.3587860979146245, - 2.7985813475724375, - 0.7094710290003688, - 2.0531183191182882, - 0.8511068042526803, - -8.590135642397662, - -7.189965033714168, - -7.154677422733394, - 0.19090233780148586, - 2.931853633383166, - 2.2561671508640466, - 0.901416475523869, - 1.7027262016250704, - 1.971219776112316, - 2.4174107152765125, - 3.0487575561656595, - 2.924163384267368, - -7.054310537828337, - -8.28566569244672, - 0.7085209499196015, - 2.6833955075498936, - 0.8698284742955038, - 3.0152347189355497, - 1.2579402799717339, - 3.2603225427799205, - 0.1782881730598257, - -0.42615362191586, - -7.6490739603896785, - 0.3077973439238357, - -8.900953410878762, - 0.20201870504381775, - -8.423384087563129, - 2.722527284583259, - 1.3910530785859019, - 0.3946761807726644, - 2.8332292593118793, - 0.8936884956897678, - 1.1787387461648193, - 1.567348877300945, - 2.2045001284416883, - 3.3631224988915234, - 0.04816168052311782, - 2.1389438147027393, - 2.731851521918433, - 0.6069927084759039, - 1.298579162371399, - 2.476184318231664, - 1.607135746688546, - 2.873246076164953, - 0.20254332006482556, - 3.2014673304770636, - 0.6497769827541435, - -0.9030778286503153, - 3.431642966558377, - -0.5037706052510608, - -0.2718177142045583, - 2.3794794835113224, - 1.5218843153608947, - 2.7417262156712914, - 1.5111841271116933, - 3.3016623670243375, - -0.8018726566463645, - 2.0817782033989625, - 1.4761472522587435, - -0.3830622843308061, - 2.96125695796714, - -6.458820226724634, - 2.8812453262878064, - -7.737636277265019, - 0.47866633406865, - 0.7686251627279825, - 0.6575443015225664, - 2.717223225558806, - 1.4511419170513968, - 0.5653414107484783, - 1.7957559372188365, - 2.802780980402567, - -7.803092629931442, - 1.869341396799709, - 0.8432598728970127, - 0.7274576465338105, - -0.056347721327875196, - 1.8111595457186436, - 2.012187082121611, - 2.6766884228160452, - 2.2395446030241155, - 2.0220035695704683, - 2.551669192710943, - -7.084275988118852, - 3.2160814880125, - -7.512818306561267, - 0.2651693233580314, - 2.709930601235107, - -8.25308000044569, - -7.931544018548265, - 0.611974022845457, - 0.6022362872430828, - -7.881514129199376, - 0.2976247285209178, - 2.425138890802724, - 2.6235880841735737, - 3.035755884725319, - 0.08067025748216224, - -7.378277352583638, - 2.684047451077735, - 2.1405945720061563, - -8.180315407048122, - 2.8092973588605585, - 2.0990750518716936, - -7.957518989117321, - 0.47518320727383545, - 0.3367399214742779, - 2.2771983564378764, - -7.800606427520901, - -0.7464765130831107, - 1.448488093446764, - 1.712299710929907, - 2.3905323834778778, - -8.509083225983312, - 0.5528745670823761, - 0.056218070305737056, - -0.6790425174878887, - 0.3472145623189714, - 3.0225355309737423, - 1.633286832099552, - 0.5266672630777911, - 3.6459537790447833, - 2.236649898911319, - -0.40944473333247927, - 0.6850113779650434, - -8.21619992893973, - 2.1304260290468564, - 2.723864737812909, - 1.3399722497086435, - -6.775697936934701, - 2.3964616584226683, - 1.3842313378533297, - 2.7615107981919227, - 1.7408744101042368, - -7.738718786684235, - -0.919610965593588, - 2.0792344954104793, - 0.9850629393893267, - -5.201540497852601, - 0.1823978516841003, - -0.22885521322494967, - 0.21747576894502027, - 2.19322258510467, - 3.2986334553791505, - -8.619684862683377, - -8.309541341330789, - -7.835321833014975, - -8.764712564101124, - 0.4055112088733752, - 0.09600089149065433, - 1.0886691275686606, - 1.0145068198945755, - 1.0888323325702034, - 2.0683632581969045, - 0.9895286989042258, - -8.600637855511625, - 0.17563402960720662, - 2.9883877363976623, - 3.0891431470855233, - 0.4400202797717173, - 2.029800770955799, - -9.112364152978662, - -7.851845284401957, - -8.887578129757253, - -6.59489218895868, - 0.21776659706458837, - 1.9634443338982246, - 1.0414843328983996, - 0.469215937663879, - -7.298687916443551, - 0.7135889748814117, - 2.4196631407822804, - 0.3076025091214727, - 1.3017289266943042, - -7.020706662519961, - -7.268765471299113, - 2.1993518896259134, - 1.3378718213097844, - 1.1520314971425436, - 2.4649510119124662, - -8.44771242798184, - 2.148046492351158, - 1.454621827239103, - 3.0266238416161153, - 2.2834842529185346, - 1.6493444110044522, - -0.2807564957450657, - 0.9869961857361259, - 1.196311234640384, - -0.03138504857722978, - -8.302173262858318, - -7.147662968691874, - 2.4203753479775765, - -7.200195535346051, - -6.121405179007928, - 1.446540869790915, - 2.4946091536424513, - 2.5317860291442043, - 3.08885700076078, - 0.686600318537168, - 1.9712547495650867, - -0.3406283631713244, - -0.1917046102063393, - -0.34626361744265993, - -7.146658637459202, - 1.3912626769594616, - 2.101908290357388, - -8.951955330528236, - 1.3382607486557812, - 3.0197774381417752, - -6.705803972980068, - -6.319106555034937, - 1.3228667939258831, - -7.181379021616384, - 0.8231254810629439, - 1.6096906991986024, - 0.022087670079872737, - -6.322223274773663, - 1.9142490369319745, - -8.8395741689585, - -6.7066508601620445, - -7.861254754341756, - 1.1913256927324036, - 3.3503200114900453, - -0.002659230132193009, - 0.7771927695492519, - -8.499741678847203, - 0.17494165662536784, - -6.35141558349304, - 0.7622898073252403, - 0.4285016657869558, - 1.149946839332002, - 1.7000250524900118, - 0.609892291556713, - 2.2464330993860964, - 1.2761432007451525, - -7.398300341150756, - 2.5135528106361136, - -8.818914883272242, - -0.5170330719567374, - 2.1053277386851357, - -9.129669203870366, - -7.274116432853194, - -9.138206918075909, - -0.17477826504362012, - -7.755516593671772, - -8.460406129073084, - 1.615219452962977, - 1.0557400143215432, - 1.3559188758553349, - -6.746612576630017, - -8.427016362142876, - 1.5538988907147384, - 0.9101032737721856, - 1.1443464196683368, - 2.548440430962473, - 0.2644421770757484, - 1.0395390384388348, - 1.3279202568763526, - -8.753212949759881, - 1.4004389951274052, - -9.186945950420203, - 0.1958855237232713, - -7.954922238118083, - 2.9082245870181613, - 2.3287302443115694, - 2.6926289649200346, - -8.148594251795902, - -7.839235694550561, - 1.2882149500697657, - 0.11489142233158645, - -7.791723998974786, - -8.273808442110104, - 1.4749481617406814, - 2.308452285743202, - -0.19107627716397657, - 2.0404769868284305, - -7.985717654331616, - 1.2107905054682147, - 2.7728430561860087, - 2.3684759764589596, - -7.816121343046642, - 2.1400333002462677, - 1.3579178690393816, - 1.4137790688956473, - 2.0282163403938696, - -0.32634073086743637, - 0.13456806137205918, - -0.07652955293384209, - -8.729145156318214, - 1.2956587419826326, - -8.051340353153803, - 2.7730771407884194, - -7.954770826966083, - 0.6108161558439745, - 0.4636852274811087, - -6.185525634375222, - 1.9723213500676102, - 1.1661462020860072, - -0.127179504501362, - 0.22175017909053582, - -8.439166693494329, - 3.6310621292827308, - 1.1202246125640114, - -8.696202059696393, - 2.4645177606532807, - 0.03848449495185448, - -7.061346258741949, - -7.880999495057979, - -7.652141323360686, - 1.9346967782332938, - 1.8519134375341029, - 1.045358025225612, - 1.867882738618223, - -0.29347325176852873, - 0.8858271759641015, - -7.369184353233702, - 0.10839110864985028, - 1.1973366351322996, - 0.932204017410818, - 2.2627473995350016, - 2.947677434897453, - 0.9432060861694127, - 0.05395284885089928, - 0.889687036155159, - 1.7276491304778132, - 3.4987625677755085, - 2.346194337240592, - 1.4351247091556645, - 0.8923018476658329, - 0.8265583627496746, - -7.870220121771367, - 3.1760069390670287, - 1.8509322432764934, - -7.808546169673091, - 2.8237190425263408, - 2.946952661753927, - 1.7308140156045613, - 0.9977879893701315, - -0.5708308107304996, - 0.07889506960533402, - -6.643437055613775, - -0.56528230535463, - 0.870224700285937, - 2.6916260628152835, - -7.828681811589555, - 1.3279773734160638, - 2.8973836999999003, - -7.929287638220337, - 1.1193036378595262, - 3.594043711978328, - -8.13911330674277, - -8.90486254564379, - -0.2957064939222399, - 0.8663816353200503, - -8.521579935310447, - 2.3157669071904206, - -8.119140992084624, - 2.6021021719824646, - 2.2603643030736924, - 0.8741761862261239, - -0.06006143611101942, - -3.1598465288412205, - 0.7185513031937687, - 1.1488660787139893, - 1.439320893331675, - 0.6558899732621498, - 1.3376290043476202, - 0.33866355369779044, - 0.49100124614685187, - 2.0732762735938026, - -0.17658301058699613, - -0.15211639502969043, - 0.26358826632899807, - 1.5898050628603841, - -7.571158183163497, - 0.5023378932875282, - 2.5664867528077773, - -7.752126581163239, - 1.5202060246679063, - -7.586353065525089, - 2.458743346964622, - -7.117655044831394, - -0.2766314552971195, - 1.4995385114633468, - 2.047751662904562, - 1.7034799222273926, - -0.20718681963969204, - -0.09499902849411072, - 3.231440450246778, - -5.725631186022914, - 1.152706025263952, - -0.8436966252912544, - -0.42918929142871276, - 2.537290305930872, - -7.628772256548188, - -7.374689762871147, - 1.061013263717064, - 1.962147458108563, - 2.3280301886732393, - 1.24919179774868, - 0.8767430061555562, - -8.06549023313639, - 1.0800306557640134, - 3.1190590402572766, - 2.7199558294175286, - -7.759909637482053, - 3.189223805081286, - 2.7779181975289386, - 2.3847605509285104, - 3.329954274336646, - 0.9938937020826742, - 0.4984620320293087, - 2.831849103378229, - 2.265552368615562, - 1.6462215082838754, - -7.707758932585142, - 1.0978755588155906, - -7.9210876752988835, - 0.5379123234590063, - 1.8476018914385226, - -8.715940582759224, - 2.2899960983145, - -7.010182624606673, - 2.1097220914326766, - 1.8062889811487706, - -8.667243244723918, - 2.5551923428204635, - 1.7707424165846375, - 2.917138503950332, - -0.6786053381483399, - 2.7201581612918875, - 2.7011790013409924, - 1.2685343752484828, - 2.609497641079454, - 0.328462313212367, - 1.8540862208537516, - 0.9111878083785402, - -0.28426319299110525, - 1.928068219117086, - 0.9823570695344068, - 0.8036169357123898, - 0.8638327636608106, - 1.5631105979370687, - -8.579141238483885, - 1.9726952954724573, - -7.98143064290487, - -8.411479380206911, - -0.31646714121733316, - 1.9135385993316474, - 2.089089710673739, - 1.9960922223992736, - 0.6950167358804251, - 3.075747505339304, - 2.340950812292796, - -8.993901506596375, - 1.3335940745655013, - 1.5029656732086905, - 2.547186244573038, - -7.177198157100625, - 2.020910148648964, - 0.575026245669857, - -8.722887642994142, - 2.3931476392962545, - 1.9883487781163314, - 3.185344417621772, - 0.4611860136178839, - -0.5182075979179117, - -8.30489727021605, - 1.8201609543537527, - 3.0689388476915873, - 2.173698425464305, - 2.706005868873169, - -0.618837066000761, - -8.14167270676203, - 1.1838694232674125, - 0.5789388369320245, - 3.504126154437088, - 3.588433303842934, - -7.5506588361234215, - 2.061290460031166, - 2.646008007089369, - -8.528312183408428, - 1.7989478462750759, - 2.3431068088473297, - -8.607046603987758, - -7.233462314309418, - -8.236210998622116, - 0.7601890495346417, - 0.8199533451747715, - 2.8988379269433366, - -7.2460258547667395, - -0.04260741710161611, - 2.543539577935952, - -8.565529430160256, - 0.8452684387141972, - 0.02137488235097795, - -0.4171229078550339, - 0.5329862737316927, - 2.429445635061916, - -8.702289720690896, - 0.27413419442950115, - 0.778047647796611, - 3.1213402599631923, - 0.6452591727752793, - -7.067189783892758, - 1.9131896533628667, - -8.563014949448029, - 2.5352804472036112, - 2.2290075909502245, - -0.3470878959227531, - 1.105668261238746, - -8.376087342183945, - -8.15269169773546, - 1.3711035698490532, - -0.36426272454991426, - 0.7551506444748286, - -7.757463803645644, - 1.5490100734886154, - 2.313830351044823, - -0.8541111915958685, - 0.496654227916699, - 2.659244403352773, - -0.4430331751416259, - -6.629243243300451, - -9.01836562393277, - -8.267930482302894, - 0.3592826993210026, - 0.10107159656091669, - -7.887902440252809, - 0.5279084501674415, - 1.2915579555085936, - -7.355768275596031, - 2.469362161506793, - -7.102518289138929, - 1.852060918877644, - -8.718197701309421, - 2.965847630372054, - 1.6860490514540332, - -8.510593223376, - -4.536688807086601, - 2.0334442262280485, - -0.3426201204341113, - -8.453688176881816, - -8.342615611274992, - 0.9115626260883183, - -8.66913823054388, - 3.211134229958071, - 1.5064447559646312, - 2.425614930885676, - 2.1285963080005565, - 3.6280943058081268, - 2.3581021902785757, - 3.443999940056457, - 2.4524429553642957, - -7.630602134495716, - 0.9749722474485204, - 2.023063317973442, - 0.4449547911800854, - -0.6651643924572769, - -8.977257191576923, - -0.09940376983580983, - 1.0983446316458962, - 2.957566880493749, - 2.231581703132769, - 2.992648636070979, - 0.10029857579906186, - -0.10486224630613837, - 2.7052214883187347, - 1.7321038147581467, - -8.553642928754616, - 0.7678399545232438, - 1.7369801350368201, - -8.959210380086098, - 0.39429857882813435, - 1.5829811856819702, - 3.2572325544113223, - -8.304367400379208, - 2.3880265079951997, - 0.9446753401638908, - 1.8016424209164952, - 1.8749987305003346, - 2.5381615514093196, - 0.9140264280810966, - 1.6888308847238722, - 1.4701940930143365, - 1.3672739186583218, - -7.978877810221675, - 1.751007663957888, - 2.762920710051229, - 3.1207677452514786, - -8.294409328210083, - 2.118279801483606, - -9.136774027043517, - 1.2960232456627068, - -7.6203490396486115, - -7.170062781547793, - 1.4606818503734946, - 2.254454243477766, - 0.4888493896618929, - 2.445951735545381, - 3.130901934841017, - 2.0169064244671624, - 0.5781320235978845, - 1.164559165113405, - -7.085727391465785, - 1.5563134560808463, - 2.5246786453408587, - 1.8306790539513156, - 2.063158354285914, - 2.951222072815112, - -8.011694407902795, - 0.6912192194209621, - 1.7567867998704312, - 1.227745741829922, - -0.15483148523896537, - 3.080062309803283, - -7.014075101217134, - 1.7153006739574652, - 0.42563776715604157, - -0.20460280950116075, - 0.08112706131989966, - 2.3249243480067583, - 2.8599522371258654, - 2.8250697629458648, - 1.3263597524146535, - 0.6689904965545804, - 1.7211640556971661, - 2.664252570995877, - 1.9021155590745604, - 1.3039480575116782, - 1.6186179551129143, - 0.6994200226046031, - -0.2762234251771253, - 1.6463651245781266, - 1.714335455602332, - 2.863930022411937, - 1.5345625659420514, - 1.9874458198165799, - 0.6236563963009678, - 0.5487365154798838, - -7.699812241244133, - 1.9022132491593855, - 2.0582611608232324, - -8.241695983493726, - -6.6537679124807, - 2.1727184060924447, - 0.9273336782436994, - -4.084132513497494, - -6.170446784167851, - 0.16227905402765097, - -6.5818959164282065, - 0.3856228859005982, - 1.0640002227515153, - -7.938741293583762, - 2.093082240549366, - -8.7906152886363, - -8.901765187372959, - 3.8337110169924444, - 2.1154827591984047, - -0.024563247863549253, - 2.265518351996009, - 1.9006504722937423, - 1.917766167905046, - -8.633956025491374, - -8.851789595046611, - -0.38659176008223367, - -8.87236621013963, - -8.501176765733607, - 1.9191111526959272, - 2.0092982704073235, - -7.981956809324846, - 1.4206166475637727, - 0.6387858496083604, - -4.240260019432114, - 1.3929661181125392, - -8.64662315068952, - -7.421202866081349, - 0.007880371938225328, - -0.19056302410489345, - 0.503120685047802, - 2.1688687868026357, - -8.292235911623273, - 0.4841239485526286, - -0.21587616980271407, - 2.6559586365930166, - 0.8458314061382362, - 2.06133046178105, - 2.6770161025917525, - 2.2054628111229193, - 0.15780246248383983, - 1.8897321611408149, - 1.1275903344847946, - 0.7875862341118278, - 2.1134528176796077, - 0.043938642482980586, - 2.215455707867413, - -8.456452178054775, - -8.692009213476931, - -0.5101357762192221, - -4.421699075118912, - -8.284672622364882, - -8.836080267171257, - 0.2811631865005029, - 0.7142526358338925, - -0.30874882508807805, - 1.7719153462076291, - -7.779768112165598, - -0.2753804205635559, - 1.9260020511696359, - 0.05227095637109941, - 1.1788794487568979, - -6.726659315471383, - 1.6706662165839776, - -8.947952635047871, - 3.162863553794859, - 1.5389964899535564, - 1.2544440603559768, - 1.7145010953616646, - 0.4822413648004758, - 0.8802826978220544, - -6.928476477946392, - 0.10778270716980459, - -0.39126373206777293, - 0.8622491527567213, - 0.31010488292438115, - 2.03192764830168, - -8.796503623860978, - -7.25126358436173, - 0.3351051631162634, - 2.401849776359339, - 0.9593991430845032, - 0.28888122690848994, - -7.88160986575865, - -8.795296799403625, - 1.0757305446731973, - 2.1924085737667283, - 1.0972505543442912, - -0.2774989094254504, - -7.066242301005415, - 0.11467791494875802, - 1.6091405789212163, - -7.260729719065053, - 0.33316620169517214, - 2.205281933674402, - 1.172124004482102, - 2.4696000397910645, - 2.3730224401479516, - 1.3335890617350563, - 1.7094335595127936, - 0.8208981431645013, - 1.8647377935509077, - 0.36747321127457044, - -7.060084906231471, - 2.7804890302269643, - 2.9671177107298687, - -7.505782900572595, - 1.0474434372261008, - 2.9724405167414307, - -7.635142339082416, - -7.217456677559582, - 2.727741118573167, - 0.8465807600627744, - 0.7523149050591599, - 0.5201613891793713, - 1.925880550199435, - 1.9625870722855867, - 1.010200439428451, - 0.22032048692175552, - 0.7273647588069262, - -0.1355918572976582, - 1.345341378000972, - 0.5800264441178827, - 1.380656425038407, - 1.8792469186637635, - -6.514298843285813, - 2.099765193816464, - -7.509190765310397, - -6.890897830401605, - -9.222846612291947, - -7.172078812604409, - -7.789712879680477, - 1.254734993818503, - 0.5531895666629048, - -8.612093971837751, - 2.0864710531435913, - 0.45494547747797875, - -5.508790997390626, - 1.1149993703403722, - -8.0440977364811, - 1.6559663293874263, - 2.420212513816951, - 2.9853181372794784, - 1.515004941287756, - 2.547898257908868, - -6.622344884313547, - 2.279783867318617, - -7.461243943269229, - 1.083537216055773, - -8.539160423577666, - 2.5671093694551743, - 2.5120642770654174, - 2.7201046348614373, - -8.83034854050044, - 0.40813570966610907, - 0.1478548923910506, - 1.378802988881486, - -8.145853074840295, - 0.5859367793324454, - 1.2685315732446376, - 0.5816188712363226, - 0.6475648145998375, - -9.170946475716914, - 1.1255854211133745, - -7.204255242285411, - -6.735249012873698, - 2.835288408826582, - 1.3975350610213035, - 2.0655171510622794, - -7.142744911960321, - 2.5084973350342827, - 0.39401025608934637, - 0.8413376253131408, - -8.22411101126183, - -8.316357387285601, - -8.301731394638491, - 3.1850216861049936, - 0.31145632933967327, - 0.7490086616134807, - 0.16499663357513214, - 1.3340694243972384, - 1.067740313249043, - -8.778641494106067, - 0.5323884586681293, - -6.791677941954464, - 2.7181197902959324, - -8.120989910120539, - -6.566977462156488, - 0.19971778956130795, - 1.5142333116934048, - 3.049490121824, - 1.1362102180694054, - 0.388842475083235, - -9.19938011247477, - -7.435297148324332, - 0.5219091136830705, - 1.6676803894699457, - 2.9213805693889197, - 0.6423880183415991, - -5.6180731048586905, - 3.041626787445567, - -6.6873096359841275, - -7.085387574060344, - 3.074449590208328, - -9.049286753289348, - -0.07955063623519049, - 2.547868234063361, - -9.028291326562696, - 0.7130986820012628, - 2.132638517739885, - -9.065414093828675, - -0.021756493080876613, - 0.6630241370437974, - -8.042827548943682, - 0.12705662340916574, - 0.9458870828880522, - -0.3662118100714234, - 1.0640708262928484, - 0.7090274222032339, - 2.7672877694347844, - 2.766279528804059, - 0.1334718113791702, - 1.11615265120768, - 2.6488368076661493, - 2.2412978981691953, - 0.12403072980622999, - 2.5653841751762845, - 2.46840596735832, - 0.7664635895912416, - 2.1808954147589534, - 0.7780720929790442, - 1.154606096196686, - 0.10572028977310916, - 1.2851076877131016, - 0.556425323239768, - 1.0685018048754145, - 0.7454887942125477, - 1.7527547535834673, - -7.546222752678161, - 1.3532650448586065, - 2.3714247164495292, - 1.982143701618346, - 2.618916661184878, - 2.640381933720139, - -8.385071772460382, - 0.7444984479293888, - 1.5068169150034114, - 2.2271220796396216, - 2.7368767412298602, - 2.417331566583442, - 1.1871226601686244, - -6.650805662509953, - 1.8867538961050732, - -8.809438191940412, - 1.0340198085047216, - 0.09741528294006592, - 1.1144739131504813, - 3.568290861071225, - -8.675318927552368, - 0.27057758173492047, - 1.5034740911958426, - 0.6576685640069088, - -7.970029234276875, - 2.0543143183721093, - 2.4976178443593477, - 2.592234390534009, - 1.2794420349507243, - 1.3280661268357454, - -6.1397431101450515, - 0.6493502392033413, - 2.451702099349213, - 0.3856119997859295, - -7.846337417047921, - 2.198060056284684, - -6.961349711979518, - 1.7437468720369593, - 3.0464861871275026, - 2.257505905763807, - 0.30885351917698495, - 0.8297613717282993, - 1.5747759023875523, - 1.317957570410962, - 2.553616904435545, - 1.424238444833736, - -6.409821252587784, - -3.7121101731513755, - -8.07988081118465, - 1.1581201368122398, - -8.736322415995028, - 0.6153135417031852, - 1.1851950640560585, - -8.04273204084384, - 0.3753515125893134, - 0.6044410800186297, - -0.4462806348390067, - 2.4876025235421375, - 0.4243786377495357, - 2.397867885817016, - 3.042072995902169, - -7.042235067429063, - 1.4433894825003244, - 1.3503899983375744, - 1.9267961475043072, - 0.11303028424955176, - 1.2802237387762023, - 1.1807097565574458, - -8.396811638245762, - 1.966221028236108, - 2.670565206957964, - 1.941463422585001, - -7.301573843511433, - -6.791358138871878, - -7.753009533802501, - 2.0725098091559078, - 3.3508596926505434, - -8.336750014567741, - 1.328999925878136, - -7.498577814850508, - -6.909957244961768, - 1.6808666342979746, - -9.259426955145779, - 1.0529248929166835, - -8.659503064520303, - 1.0794283442346126, - -8.169354608391833, - 1.2687417154610972, - -0.05008806804418893, - 2.554466483058769, - 2.6463387561425358, - 2.0915278486625852, - 1.963493051516514, - -0.058111812310782905, - -6.719162782261123, - 2.1286532096533546, - 2.6711102253818306, - 0.8113490399413341, - 0.1691688087031465, - 0.7576914618941437, - -8.573974536623778, - -8.202351570300284, - -5.022030620598906, - 0.7378700433168435, - -7.896595642041391, - 2.715954389554796, - -7.328039581111833, - 0.4656709743306232, - 0.38780981951749893, - 2.715794355311965, - 0.6832808179661064, - 0.8165883110436294, - -0.7747965792331853, - -8.73586196187189, - 1.4133836545434357, - 2.772935925322485, - -8.717567004542799, - -7.534740709216023, - 2.925460725713395, - 2.8751008445351975, - 3.0793788378304163, - 2.1533793279196245, - 1.7978212944486598, - 0.7107077365239324, - 1.0427976193825639, - 1.7330570013400586, - 0.00556742814150668, - 1.5612831466067632, - -6.734421807039429, - 0.4013219184744089, - 3.5262979904457143, - -8.95170377984456, - 2.2141611432455224, - -0.08047619438343041, - -5.957196390708477, - 3.3226888221987836, - -0.37803085074796233, - 2.645414596563064, - -0.33862855976270245, - -8.46555558570551, - 2.76345646211871, - 2.40494295752824, - -6.840982915756616, - -0.3242636234143703, - 2.7750295264645297, - 1.8183999533967665, - -7.678438800179548, - 1.0160749550942851, - 1.7137173475535832, - 2.8083713130665635, - 3.1604421650794694, - -0.4229217013580974, - 2.1765062672188935, - 1.0311177140396095, - 0.6027953301818604, - 3.2893079766983124, - -8.419775319138095, - 1.1517915087767054, - 3.806484015949818, - 1.813709085411365, - 1.586889829445234, - 1.0553305281082588, - 2.0387604323716473, - 0.46255061828788563, - 2.5403778903660448, - 0.8978741659153907, - 2.9667459702613748, - 1.7935809280277752, - 0.9979198425330458, - -7.348823524408095, - -8.190100691652388, - 1.013482899172069, - -8.176589705475472, - -6.776804544087918, - 2.5175129624009247, - 0.07453293651955747, - 1.1677142732080015, - 0.8121530043524006, - 1.0728087393996888, - 1.3207866981412948, - 1.391487660213971, - -7.325262871111656, - 2.480512446508523, - -0.6726147334600983, - 1.286633878671537, - 1.2848571814950263, - -8.630068144410178, - 1.641074512334856, - -8.372520390263729, - 3.6220477954119166, - 1.5476109871904122, - 1.3313072985443402, - 0.4509802411964847, - -3.676572896300967, - 0.3431658561343909, - -7.394169280242893, - 1.0111153209989923, - 0.6236978299182561, - 3.2232768877654876, - 0.9889212142907509, - 0.9557662078999765, - -0.16552310968824946, - 2.557882614305319, - 3.170986388211581, - 0.562007121308636, - -0.6890649793533657, - 2.5864702274219007, - 3.147873301590315, - 1.8452327103988686, - 2.2300578670635, - -7.914572431346472, - 1.681388435406869, - -7.934181576720307, - 1.213953350024886, - -7.767409167529324, - 0.6125353497428956, - -5.862074779777948, - -0.05579432135103433, - 1.86187714887813, - -6.831639403701684, - -8.368366805004245, - 0.7141650842394128, - -7.2296156596447805, - 1.9658449157112, - 1.203402773136181, - 3.151848920524179, - 0.8134834215896044, - -0.0015891696015058621, - -6.6206322071046335, - 2.442034190696451, - 1.4642792894623475, - -7.662456653055396, - 0.5578606457466265, - 0.4827129085038648, - 0.2447768553210342, - 1.2446398205960199, - -0.25148268369407345, - -7.866482447918518, - -6.778773007540573, - 2.364212567590591, - -8.876829124962727, - 2.3709111578808897, - 2.443004766387172, - 0.7629475448244297, - 2.5660739576610623, - 1.543324993772585, - -7.445412828672346, - 1.3108578718592787, - -7.38077750258055, - -0.06035745322128779, - -8.065274811827726, - 1.3228399598913307, - -6.855601930353441, - 0.48550708554397876, - -8.118421982992933, - 0.47680284185583893, - -7.882497296555905, - 1.250031921419141, - 1.9815759668868294, - -7.84848669377249, - 3.367580290061463, - -8.440463565239842, - 3.0765713208166643, - 2.047624797367175, - 0.4889432739407685, - 2.5096694366000163, - 1.5221815582718397, - -0.24634193428253054, - 1.9915302143198261, - 0.6635624893207551, - -7.891419294916788, - 1.5075850215925033, - 1.2568996983393395, - 2.378860296841117, - 3.1394575024244022, - 0.37361594939970977, - 0.935152027531952, - 3.047339993260869, - -6.773412066573279, - 1.0136520227701125, - 1.6683344851535156, - 1.3800348556849296, - 0.3710586489799465, - -8.01667358521836, - 0.990252834741967, - -9.126682421524748, - -9.193666922759986, - 1.9428961494619439, - 3.587663110515121, - -0.2622805993300625, - -8.393066513474231, - -8.596771623489156, - 2.302138698806313, - 2.0258880548889793, - 2.6910996993473884, - -0.6734939697369002, - 1.04114747684359, - 1.718185888051403, - 3.48276539461964, - -6.95854436686443, - 2.4735697481156858, - 2.041149990149579, - 0.673791469689127, - 2.9897117569477327, - -8.238988517507169, - 0.9761093805477352, - 1.8216332855723016, - 2.2164179615841872, - 0.4932126968317748, - 0.3780496352396801, - 2.0649711404519855, - -0.3613929635545015, - 1.530645089629263, - 2.457243579429912, - 0.05440985134375729, - 0.06784140843088526, - -0.003004518576022715, - -4.447565313413029, - 0.7159244478392003, - -7.4391021004275935, - -9.10853187457136, - 0.34616954373534803, - 0.3874840426360299, - -0.32695879149184703, - 0.7751933946282066, - 2.9773628087798647, - 2.2142437878977925, - 2.1843254988850855, - 3.059126414689936, - -7.692981165498031, - 0.3024228093713769, - 3.605203578070868, - 1.4644727704422869, - -8.727072293408847, - -8.091615408220388, - 0.4629390055507127, - -6.980247924896281, - 2.4171511912056944, - 0.9091940581067055, - 0.045724673301188894, - 3.0929852250357976, - 3.198135004353189, - -0.21094478484423296, - -8.564324258125765, - -8.810215664648535, - -6.815470170564254, - 0.9382340965406358, - 2.558848589992109, - -6.860407582762542, - -0.11677156318837643, - 1.7632932116246454, - -0.567984892256506, - 1.268764912958375, - -6.793588858602195, - 0.44299312590662765, - -6.859297675764476, - 2.587620793885912, - -6.352486573862255, - 1.1729864504462661, - 2.340260731160978, - -8.048569125070872, - 2.318283003374852, - 3.4853185969834053, - -8.250982909735939, - -7.642972426754199, - 3.2704918520039516, - -7.899950558873467, - 1.412053293639085, - 2.454183942959644, - -8.471969075893853, - 1.8275377932192616, - 1.1836780899054724, - 1.3203521358289407, - 0.9678677193752282, - 0.481491658469547, - 0.8447740588469119, - 0.9658229991595761, - -0.24011170869178097, - 2.839010771182523, - 1.9624349399608014, - -8.599242423056895, - 0.4211472361023467, - -0.2793320314444414, - -8.797108635586614, - 2.9392182781603906, - 1.256873152990501, - 1.5665471944473703, - 2.6547265873722368, - 0.8105761486188217, - 1.721884808291741, - -8.234430197275405, - 0.5536636270100801, - -8.355106987612643, - 3.178140091519325, - -7.73626088974614, - -7.144415677325785, - -6.691323046710537, - 0.18838902967814972, - 1.3810650697628872, - -8.528176568166815, - 1.8735027217692781, - 1.8177810237061083, - 1.8528978825048201, - -7.6581702947911285, - 0.9851936282135941, - 0.9749140655529156, - 3.4804614557444093, - -8.271591218158985, - -0.0692916061467144, - 0.23636074444602018, - 2.2536748103998634, - 0.6620572261158134, - 0.5272863441054563, - 0.31987648412936154, - 0.7902815603429416, - -6.85058804260707, - 1.0999584013545434, - 1.859646243461103, - -8.559557059496289, - 0.8252105446203934, - 1.886734510600049, - 1.6134861199944395, - -7.985644994531114, - 2.971573949701723, - 1.3672364573922098, - -0.3682007887540835, - -7.103789187918907, - 0.9405168733953734, - 3.4871526094460066, - 2.1859096620649496, - -0.06289084203356823, - -0.10258851143346698, - -0.18803971518510462, - 0.8634144021978678, - 2.1582894982893395, - -0.4677742138351482, - 2.0928793604794955, - 1.2878926947686777, - 2.336889592470472, - 0.6872067448511159, - -7.748766216039927, - 3.097444263728701, - 0.5556866987589535, - 2.6712301633728353, - 1.1849033710043753, - 0.5486668885120461, - 1.0907831266305195, - 0.8434242995293644, - 2.945520310117043, - 2.8605173091238214, - 2.19486511424655, - -8.827037046270771, - 0.8032457482846421, - 2.7703795059818543, - 0.0388776722783144, - 1.2645413629366868, - 2.1265867903136657, - 2.3385576793976584, - 1.917127276522154, - 1.0529020988066884, - 2.0148206403888405, - -8.191291663926195, - -0.12305657129402683, - -0.04938015097326366, - 1.3313074227837138, - 2.649367557322003, - -0.08737222278800186, - 1.8643940520501083, - 0.33554885638604737, - -0.10208068750017399, - -3.351687711644993, - 2.2491187462351876, - -7.264665631287486, - 2.468811775400256, - 2.236940253230926, - 1.4395837747782287, - 0.5756193294246122, - 1.566682837365336, - 1.1941344117585693, - 0.7864333853514603, - -9.130530246586128, - -7.542220059862066, - 1.57835349664291, - -0.5198230637738277, - 2.367130441925575, - -7.508216068087835, - 0.3251150387191636, - 0.4305638446644724, - 3.576750227255939, - 2.926957105266908, - 0.6489723337676349, - 2.6600070511561866, - 3.0978307529860145, - 2.14332749047063, - 0.8417453308787288, - -8.362638563146596, - 0.7655484851530803, - -7.358857148523173, - -8.795863146335122, - 1.7528113987581404, - 2.1996806032770424, - 1.1842707222509872, - 0.3370356510506722, - 1.5657862898662531, - 0.9954573129035333, - -8.362659182252077, - -8.572523895071708, - 0.6623382018746384, - 0.6994445665772647, - -8.812671581275692, - 0.7069222566198479, - -7.0821163329383, - 1.9549163979002904, - 2.7673886265006495, - 1.58020571085722, - 1.1157305393370385, - 1.8192078696921687, - -8.648738166417022, - 2.628514031659668, - 2.307267931960636, - 0.17720288819135216, - 1.7561274604591817, - 0.09524221875625612, - -9.01315111179075, - 0.6047127666500285, - -7.244699265066096, - 0.350818800626781, - -6.8329565403043935, - 2.2955591146423098, - 3.0182115153169815, - 2.3746049023107285, - -7.019640140605208, - 2.4647840205414395, - 1.3434268505839981, - 1.6854086164192068, - 2.295861317921914, - 2.2764302909930985, - -7.983364933412937, - 0.5807929594978267, - -8.894143291256958, - 2.9938838722469345, - -7.0788633945319415, - 1.2178067680325075, - 2.856905931248516, - -8.868555023102441, - -8.111576071477934, - 0.7355491495970233, - -8.884594494490006, - 1.3008471541908617, - 2.0846825428565143, - 0.940236823123737, - 2.6584950353466343, - 2.5762583674418824, - 3.3819401974882135, - 3.0910570249281393, - 1.2778711559145604, - -0.4827457256339073, - 0.8455691575019935, - 2.989985556284473, - -8.594252280966447, - 1.9197413450145182, - -7.46547909931198, - 1.6722748789866753, - 2.2138221464125243, - -8.270938951734585, - 1.7386397987695124, - 1.033678879096028, - -8.516503001822748, - 0.512090110414948, - 2.0059308250635013, - -7.781026228664235, - 0.36210339688697013, - 1.8975077592436573, - 0.7694797196827183, - 2.9175852118329306, - 0.35192891316867225, - 2.7464548788808485, - 1.8181456629054111, - -8.879105287057802, - 2.364591270774948, - -8.811648789232835, - 2.2303404870811443, - -7.212500783453163, - -0.04252695108275349, - -8.27691641027849, - 0.17389279156214596, - 0.3419299559039324, - 1.1168557615318893, - 2.6300729259371325, - 0.519545977271745, - 2.026006377830216, - 2.4542416541761796, - 0.6214882222636962, - 2.56545276551517, - 2.371782875552455, - -8.410901915894607, - -7.755180617297871, - 0.26854433319712717, - -0.29016912404990974, - 2.7855698716380655, - 0.7031441386051922, - 0.6463634663828767, - -0.14572491547363256, - 1.0846660011879703, - 2.9877269537925093, - -7.4014817343606, - 1.532485901854579, - 3.2834185214330414, - -8.395186846378069, - 0.7067177076339348, - 1.790307058312988, - 1.9045140645897747, - 0.8155319473452132, - 1.558527430207653, - -0.4562439874529775, - 0.6283683976770774, - 0.3170889013577815, - 1.2269672091211687, - 0.13239083090554576, - 0.9672200895075614, - 2.3228852138079854, - -4.508240674846544, - 0.937926825482767, - 1.9403937731548746, - 2.5476778851631727, - -8.791030377657798, - -6.90900624236735, - 0.38668188599048714, - -8.387398417504254, - -7.344755132587228, - -8.401990418987419, - -7.427545106366351, - 2.052933392737336, - 1.243724639000523, - 2.492261060779638, - 0.9113773906922337, - -0.15816106323304419, - -7.470553956059105, - -8.846441596666375, - 2.827116680018038, - -7.116712997211687, - 1.2433205851368418, - -8.346468787028506, - -7.978333067918487, - 1.172963260744282, - 0.2608874203114955, - -0.46724686695630874, - 1.0564086871641414, - 0.06130467277244044, - 1.6818877741501426, - 1.318743028841478, - 2.8373390653938273, - 2.576615766795672, - 1.2681807565928347, - 1.4580249782652615, - -6.524433867154633, - 0.09581451622485024, - 1.8231985588689075, - -7.358029518015586, - 3.511196746259249, - 1.8394281143396174, - -0.6754116281933468, - -0.020197099799179743, - 2.1780440921947566, - -7.409891359292506, - 1.052901385861119, - 1.2241086946853335, - 0.3665532298720331, - 0.14478725159505287, - -8.151941019411806, - -6.704773956752906, - -6.115756625251118, - -6.974690256772126, - 2.0210836961226892, - -9.015001772676642, - 0.2646431501384486, - 1.6940258171839286, - -0.2610635405056007, - 1.7344415107250657, - 2.4462330102590086, - -7.068860147884828, - 0.08695837348604589, - 1.8701982293321116, - 1.0504262384847716, - 0.019527985748346775, - 0.5097245787288074, - 0.2389915874027862, - -0.19218159389880246, - -8.855488867463228, - 0.6020616642969194, - -8.09265510730711, - 1.3150371364975184, - 1.4759405666726864, - 0.6125503265197201, - 1.0338508449971633, - 0.8355074008305553, - 1.5657388390288403, - 0.19060171190029251, - 1.9216391475271553, - -8.552212424405148, - -0.10872450136022829, - 1.5803257663654455, - -8.312807240378005, - 0.19254420609740558, - 1.5921086618162703, - 3.0724652883798753, - 3.119585347470178, - 2.3680946054804948, - -8.996751873936851, - 0.5450779135596553, - 0.3631979793991185, - -0.08367913106684004, - 1.523933920210135, - 1.9337098908579557, - 1.618362115241489, - -0.2920987527409687, - -0.08027388569056067, - -8.473382618231554, - -7.768478821668898, - -7.782876606094697, - 0.12206627215748748, - -8.662712369595276, - 0.7044770310142159, - 1.2240212148539857, - -6.580456328124205, - 1.0167328126861905, - 2.898843091197227, - 0.587714076153449, - 0.6216570749055097, - 1.0414748533858058, - -9.219472775085773, - 2.2001939905709453, - 2.094708624460661, - 1.746527945940157, - 3.03051313566259, - -7.249968841919131, - 1.3408108007543746, - -8.166942766681114, - 0.979736597403027, - -7.324885568806586, - 2.6278233426622917, - 2.854107404015036, - -8.315196696814988, - 1.64949805448383, - 0.9702802532651041, - 0.7306766790583936, - 0.5492725402351939, - 0.9757266772327314, - 0.5017028463917943, - 3.1800094770093223, - -9.145099532522584, - 0.5049374526866867, - 1.386725096088461, - 1.3587664430780686, - -7.140336167363484, - 1.8245134915391863, - 2.073295079791952, - 0.751375960285473, - -7.606091978393865, - 2.0767323624294556, - 1.6065306443491023, - 3.235065720540448, - -8.721850121309014, - 0.7196711904884685, - 0.9816788132475567, - -8.84696255216795, - 2.626809215666006, - 2.549815866941008, - -8.911171932324867, - 0.9509628399304939, - -0.23927259256889213, - -3.875366962750523, - 1.3908433382198686, - 1.8916021423621145, - 0.7357495578652032, - 1.8923717026364686, - 0.3266032798067937, - 2.300474414349679, - 1.5890325507701302, - -0.06549343928613015, - -7.538525770096769, - 2.318466047257237, - 2.8665125668115454, - -8.153893833561344, - 2.376837200867359, - 1.4709715498404656, - -7.706214252240921, - 2.740327301519449, - 0.09028636054530002, - 3.228455947564836, - 0.5513794682867488, - -7.295604836083069, - -7.759906957734117, - -8.09777432729763, - -8.756864903683306, - 1.2763511405271517, - 2.945562275839741, - 1.3838398593194638, - 2.6854401964823555, - 1.656261678163789, - 1.7533428744601358, - 1.3611257362588403, - -8.655329830508306, - 1.2443715368140775, - -0.1609367996719012, - 0.4399722778070814, - 1.4550332512164776, - -8.299697577767187, - -6.791177821351162, - -7.296317217122517, - -4.24043076076241, - 1.9744461728026013, - 3.0169108659129678, - 2.085481071313922, - 1.5796231665236808, - 0.28883706586254004, - -7.591695100980768, - 0.6925641152794203, - -9.11235095395525, - -0.2735603783775178, - 1.1818571609991912, - -0.018031404946787462, - -8.419312407491887, - -6.567851485538858, - 1.025406857208014, - 0.9351698697703867, - 1.818433527458495, - 2.572785712333763, - -0.17393935498240165, - -9.016630101374009, - 3.2792795030834743, - 0.6658242879271989, - -4.152270499925638, - -8.157087288303547, - 0.335924182306347, - 0.9271775190846979, - -0.03618409014146321, - 1.479665880222401, - 3.3166424655428544, - -6.576355835404252, - -8.394098885439393, - -8.303510483979204, - 0.9062729084027537, - 0.899839531830259, - 1.8193688012574165, - 1.4364119637784045, - -8.767490172955053, - -8.595866558481568, - 2.894212712135655, - 3.0533541874355197, - 1.476114993804659, - -0.6692909143542188, - -7.138202852784044, - 0.21695706225651779, - -5.7962601631962904, - 3.7264192571904973, - 1.0442589644292544, - -7.076269965204877, - 1.367915964860723, - -7.544790546463144, - 1.266952685212199, - -7.804861505331333, - 0.47349039096221374, - 1.5930269805126527, - 2.5782435864991484, - -8.074721153378004, - 3.5025819239037292, - 2.9573712662329408, - -8.193982940881433, - 3.2661504885678805, - -8.948840147357354, - 0.6610691084305056, - 2.6835411548086467, - -8.934693065916505, - 2.10816139136865, - -7.548985911968935, - 2.4765230790798833, - 2.4141491397851342, - 2.739887738696199, - 1.1338375590537584, - -7.31405143327513, - 1.869248007035211, - 2.1401939557341008, - 1.2329394233202717, - -6.723686979858944, - 2.258413389809931, - -8.768330194156949, - 1.2589709754909724, - -0.3036390540432826, - 1.9527663384310978, - 1.9649532855712855, - -7.981643134186547, - 0.8111442705420386, - -8.775732723411297, - 1.2730604738899645, - -0.22849125581746754, - 1.5137214298375352, - -0.5539006361886138, - -6.960063658385964, - -3.89830422876073, - 2.8616026407122552, - 2.9130500271371296, - -6.828704833371259, - 1.0667775059630333, - 1.151566623944205, - -8.838089952827328, - 2.2104783974902467, - -7.902865224549581, - -8.302070760649276, - 0.5350976393159605, - -6.716064221510766, - 1.267120489241334, - 0.6953533727748282, - -8.502301241872468, - 1.5904998311089247, - 0.8035782114725972, - 0.4045367467954588, - -0.08084644425017389, - 3.1042891336787104, - -0.39528854294041516, - 0.568607566886694, - 3.2746664864400366, - 0.1352387754209979, - -0.43424640761761435, - -8.46713488994006, - -3.400403057005808, - -6.655886343018463, - -7.836082067870872, - 1.4006280436181675, - 1.8310149135386509, - -0.2144436816897158, - -7.662535451019991, - -0.28366331573350656, - 3.6834853049456493, - -2.8908696938583747, - -9.092271857083439, - -0.129077551303571, - 0.3467097889851762, - 0.19864145631650879, - 2.628033215265815 + 1.35285573560809, -0.47802448287846216, 2.165888749165179, + -8.69549315663449, 2.0652175331122584, 0.49520189144034144, + 1.051380238311061, 1.8418954223210249, 2.0126272839211943, + -8.406228786835502, -0.7475822029589808, 1.0398710174106818, + 2.4614340402375072, -7.780092250827048, 2.121988331057579, + 2.8140497988665834, -9.117412304441292, 0.7443418440268849, + -0.12612876310385598, 1.1799221119905499, -0.6887250690467789, + 3.0125133545646734, -7.143523307396688, 0.49794596192762824, + 2.1879318296159007, -0.04074260948831929, -1.6304621183653067, + 0.9185120650755632, 3.330950131646921, -8.249406782019472, + 2.9837694164624335, 0.6013868697229028, -7.973320868544591, + 1.2557275472097205, -9.037432741704768, 0.5272899942439975, + -7.3620383459740015, -8.710739809962973, 0.04565450184186127, + 0.9995702400422025, 1.3707704392248314, 0.4646969234541549, + 3.6660903522856345, 1.5514822021133166, 1.8014230367905788, + 0.8562655175966818, 2.528521602131749, -8.054206350208998, + 0.6986495744500447, -8.360293645270179, -7.028788335956598, + -8.117341523020128, -8.975178374370575, -0.12287461935615306, + 0.14568919159482138, -0.22935322444119527, -7.197623936888145, + 0.13018576439615953, -8.262411494404354, -9.10852755735242, + 0.7589399187829838, 1.8111041361908446, 2.0805181051825774, + -8.016584746538891, 3.1365046821015947, -8.174435180354182, + 1.8663362319091807, 3.1219524797361493, 0.6892426837009439, + 2.244499608696403, 1.5623054194259811, 2.3384273670301057, + 0.5378190418426231, 2.7951515340684123, -0.5755601568500485, + -0.5065756491480748, 2.92485140197707, 1.488221487102054, 2.209257327297217, + -8.149923929399492, -8.283361558328565, 1.2593016566196622, + -7.614791259843514, 2.0060290322527274, -7.1957257296755675, + -0.6153994129631802, 0.647621585176719, 3.825122324575844, + -0.617206942026205, -0.0723953060051589, 2.7502344438270008, + -8.316773079712256, -0.12703127087171923, 0.032541047575098556, + -8.366227754298668, -6.412773785556261, 1.3622057178832003, + -7.233870565183863, -7.394245052883867, -4.525292336025702, + 2.10907364705061, -7.274801711351849, 0.4465992849099335, + 3.4309033386585783, 1.9395204719917993, 0.023946918636043358, + 2.833582913855396, -0.3272931840397848, 0.5946590476457169, + -4.118204094213762, -8.85541744506898, 2.4091434789774158, + 3.6121360006509553, 2.574694350221088, -8.386406382028346, + -8.087563939058514, 0.4934831447839657, 0.9560922248955092, + -9.01149783933102, 0.8918896398008918, 2.2792529871367955, + -6.807368181855979, -0.016013842245326707, 1.1749914467666223, + 0.5240606442534225, 3.5680691256852217, -7.131107288833797, + 0.5345528022913716, 2.2504990630744834, 0.43808793952614933, + 0.7054144783650844, 0.010596177968814935, -0.44663998860576865, + 2.365041933566587, 0.8319562986581416, -8.069079321353989, + 0.3509974873712663, 1.997283773551994, 2.4671002696984927, + 1.2639763865572942, 0.5352041836925608, 1.8841680192540224, + 2.905270971072112, 0.1267833933956664, 2.1242670578822405, + 2.6031580899982645, -0.4312188043186363, 0.9370138686596056, + -8.613621000724036, 3.401549960736509, 2.2160376306817655, + 0.9212426942869542, 2.7430630793423205, -0.5279990283280503, + -8.705539904925752, 2.4868955732930313, 1.9190472369020852, + 2.6080540180978486, 3.2231396825311593, -9.276648677138272, + 0.30053384369225394, -5.1928361913065695, 0.7561482591752087, + -7.571335606375206, 1.046280867035641, 0.1068853107329791, + 0.017020521216728503, 1.8023357156616873, 2.3724127779605406, + 0.9466561207261283, 1.110832640530842, 0.4122690719532064, + 2.5583580087383386, -7.3448006321193695, 2.7344695021869314, + -4.7003697238665945, 0.20345204016224966, 0.629245474557074, + 0.9436280743194153, 0.1950924896942039, -8.39321990754313, + 1.2933036946172936, 0.7299735362981703, -8.126373566878598, + -7.3662003803191425, 1.6881029482355105, 1.3907142000183166, + 2.5272762201075922, -6.930322251680463, 3.0775809978141795, + -0.07918514822520616, 2.953742730539597, -0.0017677535678961968, + 2.1886055501621033, 1.7453622702042706, 1.4951683077935347, + 1.9836262513675331, 2.501592487882715, 1.889625190366337, + 0.7353185031725933, -6.550417322255917, 0.7162273209727067, + 1.991404254201194, -0.37267481858485996, 0.5938391769786189, + -7.411420218588439, -8.212939911852136, 1.7480198752263079, + 1.370594139234737, 2.6366163782948586, 4.02933338975498, 2.0320398581703496, + 1.6817961799238048, 0.8887318601823143, 1.8216291886789278, + -8.027511231072134, -8.486856587037046, 2.735438151582886, + 0.4550883264617053, 3.3275023814892997, 1.914579541768007, + -6.3584026650996535, 0.8204178209761795, 1.3315424166556709, + 1.3732448825623564, 0.9586113508612994, 1.2104802142030255, + 1.1705199569069644, 3.2612705045348678, 1.0492599729227439, + 1.3956439354853487, -0.026480386394438813, -8.989715611105217, + 0.8107151133592344, -7.903104872958988, 0.5039574785355939, + 2.4828705420315065, 2.4115742227072956, 2.8268743166688304, + -8.105979455165985, 1.8751676391425214, 0.47027295054406565, + -7.137759512944296, 2.778992280455717, -6.954649903722504, + -8.99402332832767, 1.737009099149306, -6.436508767115393, + 0.09142569258522178, 1.4447896979783696, 3.4407425738326562, + -2.6245975457760076, 2.7538737258437753, 1.4538389571409434, + -8.714958685582125, -7.441383816313331, 0.7510754908666685, + 0.3637562228618128, 0.8399532151071638, -8.08883603972419, + 1.6310142994433159, 0.6705970298646083, 2.1442899819450436, + 0.556478231632356, -7.145388982529729, 3.0647569182319536, + -8.977111424649609, -7.711063727771787, -8.833675637290202, + 2.1741483255925496, -6.835536842196359, 3.445543676407967, + -0.5822709787922326, -8.080212990395578, 0.713903340693877, + 0.40152969027500107, 1.036963501913817, -3.9835806018617936, + 1.4744144211922672, 0.411592050621132, 0.9364087576033505, + 0.1137082665706626, 0.7301752132908366, -8.266130955066824, + 0.2735006004760863, 2.184378247744145, 2.354302848998888, + 2.5485981453437163, 1.2137100558133114, -7.247752798634288, + -8.43194359917085, 3.383507975280563, 2.2450433484087418, + -9.051751477158193, 2.8161048993789337, -0.4262984388451197, + 2.464041660712454, 1.994465005190346, 0.22374471688588723, + 2.643110468109436, 2.0702070585902668, -7.581863095749053, + -7.512666918910498, 0.6128565944808063, 0.3835269276924121, + 1.6392539494894134, 0.8320845595954978, 1.5106365905385972, 1.7720586658631, + 1.0291963010592182, 1.6418052848350662, -7.188246151127988, + 0.09198371062898206, 0.5215544251331047, 0.6371849805552529, + 3.1589727819067033, 1.268813153780352, 0.16681320384399848, + 2.1280869821189468, -9.082202106655455, 3.3172849637356663, + -6.590274113813707, -9.111097213275565, 1.8592883936797295, + -5.673139437865187, 0.2980193119458896, -4.389165578227743, + 1.8052387859523857, -7.713983531304735, 2.2016552664769455, + 3.3577319679959863, 2.7035250626548364, 2.8625973320310107, + 2.219272719282033, 2.0324556166791155, -7.081447243116417, + 1.9937689198645958, 0.9748403495325826, -8.927681326460663, + 1.3041703425278484, 1.82168902095041, -6.571880276673609, + 2.1953614271043365, 1.3750668155272605, 1.512305343143351, + 2.1735048519170364, 1.2434736921614349, 2.245753919843488, + 1.0011469888166296, 1.5077489169341487, 2.861366444731574, + -0.12975319864357043, -7.759798128516371, 1.0486401152193379, + -8.567409130119385, -8.776709766409404, 2.0523959720629676, + 0.9702463176224747, 1.2464262446181968, 1.2126888337289463, + -9.064260688467613, 0.2681989849780224, 2.0648972895331412, + 2.0441326659108716, 3.0831011651576077, 2.830334712439813, + 0.08059882892829817, -7.234692017738882, 0.6632578036213854, + 1.7306600879590341, -4.864581457973878, -9.091852992643224, + 0.07669833990740652, 0.02245052822235808, 2.8223097687713388, + 0.6186772967822212, 0.5475132602144684, 0.09821139171848503, + -7.1523470860208445, 2.6794128585643873, -7.894703748856715, + -7.997464605281789, 1.9629575179131227, 1.1035892676473205, + -8.637887747398574, 1.2205319340415708, -0.2938745402049933, + -7.00559485207825, 2.818656762828998, 1.3729772425199083, + 0.8097641508866747, 0.8410347707617063, 1.0747633751558396, + 2.773461678987149, 0.3807626926184541, 1.959034468961967, 2.050909653235062, + -7.630535795118942, -8.455389050665026, -0.13534377253691748, + 1.0909180055505898, 2.2125493767531754, 0.05717055980198288, + -5.835409235490379, -8.907589902674092, 0.6672827627892893, + -0.49655582121382663, 1.1645365854688123, 1.034959444203318, + -0.4064455989921577, -8.907457084740749, 0.09626630962876037, + -0.30648636877226526, -8.087071864621759, -8.984939584746886, + 3.254164419936194, 0.7377131144975152, 0.12653586552659382, + 1.5657379656562431, 0.16448804787290544, 2.5266905700100337, + 0.20972239604758247, 1.137118048499744, 2.7570215436697003, + -8.655373197480369, -8.228388519208059, -0.5078345067119657, + 1.5229586758713414, -7.971332052123057, 1.6870682706355173, + -7.545705194606324, -6.862974180738561, 2.0236854098282038, + 0.33415671891411824, 1.7267148126287122, 2.698653301230399, + 2.8048534205439735, -4.087625024003784, 0.16022206804150776, + 2.841513133217909, -0.5047976304668866, -7.263502458048841, + 1.123338299216964, -7.710038123638572, 2.0799806194502155, + -8.73419889042598, 0.6330292914853181, 2.1243368489395085, + -0.43313493099211564, 1.1823642197137227, -0.42859023726553575, + -0.5091823498451181, 1.9973258492370753, -8.38836915444216, + 0.7375029392148328, 2.1736812780490955, 1.738419181698482, + 1.6883070352583138, 0.5537049352527356, 2.6506657614629896, + 2.8142428026527817, 1.2235332414634719, 3.397442150460223, + 1.030353665351954, 1.3116442758866809, 1.6452859224830017, + 0.5011618044043213, -9.088557246507733, -0.01240447994027973, + 2.581084952945822, -8.463302117338767, 0.7118590055640489, + -8.130625360247175, 1.0834207438804553, 2.640358178533733, + 0.5653084044265729, 2.6702250700203165, 1.6468270224796138, + 0.846414266068259, 3.1615434834361, -7.691410230354492, 1.2557341558261315, + 0.20992282186654185, 2.477869816844542, 0.3771536857972718, + 1.9971442195608315, 0.12915305927423792, 3.2829579226358123, + 0.07537013445606805, 2.3092976438959476, 0.2329424582448878, + 0.8357888209020299, 1.2180893842173306, 0.04856351346397796, + 3.5744979379043267, 1.669535155953666, 2.3207366356258663, + 0.32681234021190014, 1.5151106657587101, 1.8281001077630386, + 3.831754713753577, 0.8185537560162401, -5.962281540225824, + 0.9255740617320212, 0.7820050943170265, -7.9288721156215605, + 1.0142181524892333, -7.707662624985399, 0.6503250943985074, + 1.380100923803612, -8.05200622560956, 1.6043286625304296, + 0.8451562069463898, 0.943690736995706, -6.704163983926268, + -7.651675754191798, 2.8069842371494023, 2.9804034094200733, + 2.512406670381577, 1.6303008295865888, 1.2743826657141013, + 2.968429649588173, 0.07981202025095484, 0.4659555505286844, + 2.4135861375911265, 0.3470879379696273, 2.096925716384769, + 1.7104732337010358, -8.93244670648019, -9.054077418131602, + 3.3272023035340923, 1.9533029770509784, -0.3578635861118119, + 1.7387635157985106, 1.0622233414382256, 1.166330984649243, + 2.290374493758918, 1.6007386358604836, 0.4069471299462136, + 3.183141909139203, -8.289505399777722, -8.735818891934889, + 1.1927270785407693, 0.8117335091610367, -6.839778391731439, + -8.560621059700626, 3.2327524190054517, 0.2351280054174659, + -8.069124435396784, 1.5934052451891958, -8.016886503130472, + 2.5166474443118187, 1.8077703556852782, -6.89917040548509, + 2.331295274393149, 0.028341084904075293, 2.45294414025638, + 2.4982955100934663, 2.6528746304421698, 0.86949660097944, + 2.9663214606223556, -0.3283375313402265, -0.38263116649533446, + -8.617634243641117, 0.9891606519058725, 0.11258801303709674, + 2.5995061442041325, 1.1101383528502828, 1.7915850107514966, + -0.39955038419449096, -8.952822233799061, 0.4338327371453445, + 1.5069996136757637, 2.2547717788501167, 2.7922905917041314, + -6.966528492028682, 0.2707484789662109, -8.526624100991679, + -4.546150834872335, 1.968289743381796, -4.085814940218094, + -8.75651859188767, 1.0492010807174819, -8.467274974407134, + 1.593124734813376, 0.3481380884273988, -0.15583301716388614, + -6.592603378805345, -7.117952854897646, 0.6178371906010927, + 0.9282037231419841, -7.644178100661795, -6.847530121470798, + -8.612602760529702, 1.9615040056293946, 1.0813198807975406, + -0.07916973209749419, 0.22878581671923293, 1.5852329652618449, + 2.6568979004682602, -8.247382625035774, -7.31905533769166, + 1.7230334499316773, 2.1442150754629377, -0.3913867311853231, + -8.565731523795018, 0.48836673876161385, -8.550981123529034, + 2.0765156901835993, 1.1791232493554893, 0.4628133554809247, + -8.570612481576456, 0.31743916249521, 1.3689304528387372, + 0.9202159446125323, -0.2270501708321309, -6.940721954427759, + -7.061116366059591, -0.2987105617995114, 3.283450614839531, + 2.1621752246384274, -8.016471862737987, -8.167882170647548, + 3.0123025587277055, -0.12776957890467389, 0.6576203647895076, + 1.2206369385103255, 1.7771949646291936, 0.870129676006453, + -6.896514945865017, 2.72395569606518, -0.708821266359798, + -8.178817525909968, 2.599012631508349, -7.4413028157194345, + -8.860103070305422, 3.0123938603834906, 0.6840626894874334, + 0.10459117875634981, -0.3227860929645202, -0.11296946986870815, + 1.8379339717420056, -7.758420382491858, 0.2711735110428051, + 3.008850738872426, -8.328873089908148, -0.6434888208653092, + 1.381037343424551, 0.4312276140533374, 0.5825181663460871, + -6.970927901949955, 2.0695117930134517, 0.6152340280892129, + 3.49595199368453, 0.6938727172986299, 1.4475996148194237, + -8.609142018851355, -7.7772768844184315, -7.544894885797945, + -6.908331226910449, 0.9089285567242396, 0.9387047714748711, + 3.7148527852348368, -7.2476532791433765, -8.998549396936156, + -6.595387338748019, 1.438191259922225, 2.288214765306113, + -0.014760414413903546, -7.770974287483711, 0.6453677444470884, + 2.087141400809658, -8.01699871457284, 2.400436142220324, 0.9203163748065302, + 2.9250246221734177, 1.739337623547591, 1.0263075400063275, + 1.2133803601560305, 0.8477548670296504, 0.2776668814036649, + 1.476863079748618, 2.38986676603255, 0.8190010540303145, -8.600849114974137, + 2.466931763065777, 0.6942828631671454, -0.48472949679486216, + 1.3690461720825393, 1.1386794631201784, 2.3000790452898423, + -0.5737801992789094, 1.4894503198246298, 2.20744903509327, + 2.346612854012468, 1.9262174442593494, -8.518158953023475, + 1.2307221290531465, 2.1206736732011553, 0.4899710406891571, + 3.1006385409976778, -7.521213500124812, 0.5237439927790518, + 1.1519603194807617, 1.6256078327550763, -8.914362686096426, + -7.845587362754366, -8.485506628202467, 1.9268753736882878, + 1.3412107413635537, 1.7626357558833163, -0.3848726650847515, + 2.0535608777636822, 0.6386486562532143, 2.1668214225250875, + 1.7621364606735226, 0.144604733364891, 3.2287546365823094, + 2.1172647727359086, 3.2498858720172166, 2.910690182828211, + 0.5560038424597556, -5.053249259330138, 0.1267741317413434, + -7.7520600294259765, 3.0099939457558884, 2.530862687511373, + -7.569045043727168, 3.100572766345718, -7.598035533924212, + 3.0812254019580134, 2.665871025642842, -7.783751872917371, + 0.7792923984254838, 0.13550411979575336, 1.9555605803234042, + 2.8109919605641784, 1.4302939303354323, -7.077889093884513, + -8.81451549884432, 1.7948047097881592, 1.3136659105045494, + -0.05431808661282797, 2.1745446641766275, -6.744529238152495, + -7.639481164896453, 1.9508598546238556, 2.994506265077541, + -8.047126695755605, -7.9055428000056445, -6.880506675107962, + 1.2064549161519937, 2.40303126836893, 3.721222591763574, 1.0392622357574917, + 0.989513670148371, 1.111295715578283, 1.5197712593885788, + -0.003830666980349542, -8.871502646042059, -7.710228767479039, + 1.316567130437144, -8.153346603694768, -0.3065364380133689, + 1.1701046228289196, 1.4383032441394334, -5.3338371145364105, + -0.4210221997984218, 1.6444079959956204, -8.877769334741437, + 3.103492802343518, 1.516321164532454, 0.04550566552419573, + 2.0988285005728082, -8.805073663059847, 2.238823922089626, + -7.760574953561919, 1.7399929534231842, -6.362716239042421, + 1.342770941232623, 0.2942419947671681, 2.460133192304222, + 3.1160109542981256, -7.863404589522134, 1.339783928604639, 3.1828691359625, + -7.419356727249834, 0.7064775403365423, -0.30887312014924456, + -8.456035013610844, -6.53454968512149, 2.178316715644698, + 1.6842159505158856, -9.021975554572357, -7.507648493713097, + 3.202200540495128, -8.100426309998456, 0.9594422746731098, + -8.845494271765292, 1.175056685814502, 0.04214137587627019, + -0.5673660022469825, -9.20656186730306, 2.973187278981339, + 0.5737719406547798, 1.3587860979146245, 2.7985813475724375, + 0.7094710290003688, 2.0531183191182882, 0.8511068042526803, + -8.590135642397662, -7.189965033714168, -7.154677422733394, + 0.19090233780148586, 2.931853633383166, 2.2561671508640466, + 0.901416475523869, 1.7027262016250704, 1.971219776112316, + 2.4174107152765125, 3.0487575561656595, 2.924163384267368, + -7.054310537828337, -8.28566569244672, 0.7085209499196015, + 2.6833955075498936, 0.8698284742955038, 3.0152347189355497, + 1.2579402799717339, 3.2603225427799205, 0.1782881730598257, + -0.42615362191586, -7.6490739603896785, 0.3077973439238357, + -8.900953410878762, 0.20201870504381775, -8.423384087563129, + 2.722527284583259, 1.3910530785859019, 0.3946761807726644, + 2.8332292593118793, 0.8936884956897678, 1.1787387461648193, + 1.567348877300945, 2.2045001284416883, 3.3631224988915234, + 0.04816168052311782, 2.1389438147027393, 2.731851521918433, + 0.6069927084759039, 1.298579162371399, 2.476184318231664, 1.607135746688546, + 2.873246076164953, 0.20254332006482556, 3.2014673304770636, + 0.6497769827541435, -0.9030778286503153, 3.431642966558377, + -0.5037706052510608, -0.2718177142045583, 2.3794794835113224, + 1.5218843153608947, 2.7417262156712914, 1.5111841271116933, + 3.3016623670243375, -0.8018726566463645, 2.0817782033989625, + 1.4761472522587435, -0.3830622843308061, 2.96125695796714, + -6.458820226724634, 2.8812453262878064, -7.737636277265019, + 0.47866633406865, 0.7686251627279825, 0.6575443015225664, 2.717223225558806, + 1.4511419170513968, 0.5653414107484783, 1.7957559372188365, + 2.802780980402567, -7.803092629931442, 1.869341396799709, + 0.8432598728970127, 0.7274576465338105, -0.056347721327875196, + 1.8111595457186436, 2.012187082121611, 2.6766884228160452, + 2.2395446030241155, 2.0220035695704683, 2.551669192710943, + -7.084275988118852, 3.2160814880125, -7.512818306561267, 0.2651693233580314, + 2.709930601235107, -8.25308000044569, -7.931544018548265, 0.611974022845457, + 0.6022362872430828, -7.881514129199376, 0.2976247285209178, + 2.425138890802724, 2.6235880841735737, 3.035755884725319, + 0.08067025748216224, -7.378277352583638, 2.684047451077735, + 2.1405945720061563, -8.180315407048122, 2.8092973588605585, + 2.0990750518716936, -7.957518989117321, 0.47518320727383545, + 0.3367399214742779, 2.2771983564378764, -7.800606427520901, + -0.7464765130831107, 1.448488093446764, 1.712299710929907, + 2.3905323834778778, -8.509083225983312, 0.5528745670823761, + 0.056218070305737056, -0.6790425174878887, 0.3472145623189714, + 3.0225355309737423, 1.633286832099552, 0.5266672630777911, + 3.6459537790447833, 2.236649898911319, -0.40944473333247927, + 0.6850113779650434, -8.21619992893973, 2.1304260290468564, + 2.723864737812909, 1.3399722497086435, -6.775697936934701, + 2.3964616584226683, 1.3842313378533297, 2.7615107981919227, + 1.7408744101042368, -7.738718786684235, -0.919610965593588, + 2.0792344954104793, 0.9850629393893267, -5.201540497852601, + 0.1823978516841003, -0.22885521322494967, 0.21747576894502027, + 2.19322258510467, 3.2986334553791505, -8.619684862683377, + -8.309541341330789, -7.835321833014975, -8.764712564101124, + 0.4055112088733752, 0.09600089149065433, 1.0886691275686606, + 1.0145068198945755, 1.0888323325702034, 2.0683632581969045, + 0.9895286989042258, -8.600637855511625, 0.17563402960720662, + 2.9883877363976623, 3.0891431470855233, 0.4400202797717173, + 2.029800770955799, -9.112364152978662, -7.851845284401957, + -8.887578129757253, -6.59489218895868, 0.21776659706458837, + 1.9634443338982246, 1.0414843328983996, 0.469215937663879, + -7.298687916443551, 0.7135889748814117, 2.4196631407822804, + 0.3076025091214727, 1.3017289266943042, -7.020706662519961, + -7.268765471299113, 2.1993518896259134, 1.3378718213097844, + 1.1520314971425436, 2.4649510119124662, -8.44771242798184, + 2.148046492351158, 1.454621827239103, 3.0266238416161153, + 2.2834842529185346, 1.6493444110044522, -0.2807564957450657, + 0.9869961857361259, 1.196311234640384, -0.03138504857722978, + -8.302173262858318, -7.147662968691874, 2.4203753479775765, + -7.200195535346051, -6.121405179007928, 1.446540869790915, + 2.4946091536424513, 2.5317860291442043, 3.08885700076078, 0.686600318537168, + 1.9712547495650867, -0.3406283631713244, -0.1917046102063393, + -0.34626361744265993, -7.146658637459202, 1.3912626769594616, + 2.101908290357388, -8.951955330528236, 1.3382607486557812, + 3.0197774381417752, -6.705803972980068, -6.319106555034937, + 1.3228667939258831, -7.181379021616384, 0.8231254810629439, + 1.6096906991986024, 0.022087670079872737, -6.322223274773663, + 1.9142490369319745, -8.8395741689585, -6.7066508601620445, + -7.861254754341756, 1.1913256927324036, 3.3503200114900453, + -0.002659230132193009, 0.7771927695492519, -8.499741678847203, + 0.17494165662536784, -6.35141558349304, 0.7622898073252403, + 0.4285016657869558, 1.149946839332002, 1.7000250524900118, + 0.609892291556713, 2.2464330993860964, 1.2761432007451525, + -7.398300341150756, 2.5135528106361136, -8.818914883272242, + -0.5170330719567374, 2.1053277386851357, -9.129669203870366, + -7.274116432853194, -9.138206918075909, -0.17477826504362012, + -7.755516593671772, -8.460406129073084, 1.615219452962977, + 1.0557400143215432, 1.3559188758553349, -6.746612576630017, + -8.427016362142876, 1.5538988907147384, 0.9101032737721856, + 1.1443464196683368, 2.548440430962473, 0.2644421770757484, + 1.0395390384388348, 1.3279202568763526, -8.753212949759881, + 1.4004389951274052, -9.186945950420203, 0.1958855237232713, + -7.954922238118083, 2.9082245870181613, 2.3287302443115694, + 2.6926289649200346, -8.148594251795902, -7.839235694550561, + 1.2882149500697657, 0.11489142233158645, -7.791723998974786, + -8.273808442110104, 1.4749481617406814, 2.308452285743202, + -0.19107627716397657, 2.0404769868284305, -7.985717654331616, + 1.2107905054682147, 2.7728430561860087, 2.3684759764589596, + -7.816121343046642, 2.1400333002462677, 1.3579178690393816, + 1.4137790688956473, 2.0282163403938696, -0.32634073086743637, + 0.13456806137205918, -0.07652955293384209, -8.729145156318214, + 1.2956587419826326, -8.051340353153803, 2.7730771407884194, + -7.954770826966083, 0.6108161558439745, 0.4636852274811087, + -6.185525634375222, 1.9723213500676102, 1.1661462020860072, + -0.127179504501362, 0.22175017909053582, -8.439166693494329, + 3.6310621292827308, 1.1202246125640114, -8.696202059696393, + 2.4645177606532807, 0.03848449495185448, -7.061346258741949, + -7.880999495057979, -7.652141323360686, 1.9346967782332938, + 1.8519134375341029, 1.045358025225612, 1.867882738618223, + -0.29347325176852873, 0.8858271759641015, -7.369184353233702, + 0.10839110864985028, 1.1973366351322996, 0.932204017410818, + 2.2627473995350016, 2.947677434897453, 0.9432060861694127, + 0.05395284885089928, 0.889687036155159, 1.7276491304778132, + 3.4987625677755085, 2.346194337240592, 1.4351247091556645, + 0.8923018476658329, 0.8265583627496746, -7.870220121771367, + 3.1760069390670287, 1.8509322432764934, -7.808546169673091, + 2.8237190425263408, 2.946952661753927, 1.7308140156045613, + 0.9977879893701315, -0.5708308107304996, 0.07889506960533402, + -6.643437055613775, -0.56528230535463, 0.870224700285937, + 2.6916260628152835, -7.828681811589555, 1.3279773734160638, + 2.8973836999999003, -7.929287638220337, 1.1193036378595262, + 3.594043711978328, -8.13911330674277, -8.90486254564379, + -0.2957064939222399, 0.8663816353200503, -8.521579935310447, + 2.3157669071904206, -8.119140992084624, 2.6021021719824646, + 2.2603643030736924, 0.8741761862261239, -0.06006143611101942, + -3.1598465288412205, 0.7185513031937687, 1.1488660787139893, + 1.439320893331675, 0.6558899732621498, 1.3376290043476202, + 0.33866355369779044, 0.49100124614685187, 2.0732762735938026, + -0.17658301058699613, -0.15211639502969043, 0.26358826632899807, + 1.5898050628603841, -7.571158183163497, 0.5023378932875282, + 2.5664867528077773, -7.752126581163239, 1.5202060246679063, + -7.586353065525089, 2.458743346964622, -7.117655044831394, + -0.2766314552971195, 1.4995385114633468, 2.047751662904562, + 1.7034799222273926, -0.20718681963969204, -0.09499902849411072, + 3.231440450246778, -5.725631186022914, 1.152706025263952, + -0.8436966252912544, -0.42918929142871276, 2.537290305930872, + -7.628772256548188, -7.374689762871147, 1.061013263717064, + 1.962147458108563, 2.3280301886732393, 1.24919179774868, 0.8767430061555562, + -8.06549023313639, 1.0800306557640134, 3.1190590402572766, + 2.7199558294175286, -7.759909637482053, 3.189223805081286, + 2.7779181975289386, 2.3847605509285104, 3.329954274336646, + 0.9938937020826742, 0.4984620320293087, 2.831849103378229, + 2.265552368615562, 1.6462215082838754, -7.707758932585142, + 1.0978755588155906, -7.9210876752988835, 0.5379123234590063, + 1.8476018914385226, -8.715940582759224, 2.2899960983145, -7.010182624606673, + 2.1097220914326766, 1.8062889811487706, -8.667243244723918, + 2.5551923428204635, 1.7707424165846375, 2.917138503950332, + -0.6786053381483399, 2.7201581612918875, 2.7011790013409924, + 1.2685343752484828, 2.609497641079454, 0.328462313212367, + 1.8540862208537516, 0.9111878083785402, -0.28426319299110525, + 1.928068219117086, 0.9823570695344068, 0.8036169357123898, + 0.8638327636608106, 1.5631105979370687, -8.579141238483885, + 1.9726952954724573, -7.98143064290487, -8.411479380206911, + -0.31646714121733316, 1.9135385993316474, 2.089089710673739, + 1.9960922223992736, 0.6950167358804251, 3.075747505339304, + 2.340950812292796, -8.993901506596375, 1.3335940745655013, + 1.5029656732086905, 2.547186244573038, -7.177198157100625, + 2.020910148648964, 0.575026245669857, -8.722887642994142, + 2.3931476392962545, 1.9883487781163314, 3.185344417621772, + 0.4611860136178839, -0.5182075979179117, -8.30489727021605, + 1.8201609543537527, 3.0689388476915873, 2.173698425464305, + 2.706005868873169, -0.618837066000761, -8.14167270676203, + 1.1838694232674125, 0.5789388369320245, 3.504126154437088, + 3.588433303842934, -7.5506588361234215, 2.061290460031166, + 2.646008007089369, -8.528312183408428, 1.7989478462750759, + 2.3431068088473297, -8.607046603987758, -7.233462314309418, + -8.236210998622116, 0.7601890495346417, 0.8199533451747715, + 2.8988379269433366, -7.2460258547667395, -0.04260741710161611, + 2.543539577935952, -8.565529430160256, 0.8452684387141972, + 0.02137488235097795, -0.4171229078550339, 0.5329862737316927, + 2.429445635061916, -8.702289720690896, 0.27413419442950115, + 0.778047647796611, 3.1213402599631923, 0.6452591727752793, + -7.067189783892758, 1.9131896533628667, -8.563014949448029, + 2.5352804472036112, 2.2290075909502245, -0.3470878959227531, + 1.105668261238746, -8.376087342183945, -8.15269169773546, + 1.3711035698490532, -0.36426272454991426, 0.7551506444748286, + -7.757463803645644, 1.5490100734886154, 2.313830351044823, + -0.8541111915958685, 0.496654227916699, 2.659244403352773, + -0.4430331751416259, -6.629243243300451, -9.01836562393277, + -8.267930482302894, 0.3592826993210026, 0.10107159656091669, + -7.887902440252809, 0.5279084501674415, 1.2915579555085936, + -7.355768275596031, 2.469362161506793, -7.102518289138929, + 1.852060918877644, -8.718197701309421, 2.965847630372054, + 1.6860490514540332, -8.510593223376, -4.536688807086601, 2.0334442262280485, + -0.3426201204341113, -8.453688176881816, -8.342615611274992, + 0.9115626260883183, -8.66913823054388, 3.211134229958071, + 1.5064447559646312, 2.425614930885676, 2.1285963080005565, + 3.6280943058081268, 2.3581021902785757, 3.443999940056457, + 2.4524429553642957, -7.630602134495716, 0.9749722474485204, + 2.023063317973442, 0.4449547911800854, -0.6651643924572769, + -8.977257191576923, -0.09940376983580983, 1.0983446316458962, + 2.957566880493749, 2.231581703132769, 2.992648636070979, + 0.10029857579906186, -0.10486224630613837, 2.7052214883187347, + 1.7321038147581467, -8.553642928754616, 0.7678399545232438, + 1.7369801350368201, -8.959210380086098, 0.39429857882813435, + 1.5829811856819702, 3.2572325544113223, -8.304367400379208, + 2.3880265079951997, 0.9446753401638908, 1.8016424209164952, + 1.8749987305003346, 2.5381615514093196, 0.9140264280810966, + 1.6888308847238722, 1.4701940930143365, 1.3672739186583218, + -7.978877810221675, 1.751007663957888, 2.762920710051229, + 3.1207677452514786, -8.294409328210083, 2.118279801483606, + -9.136774027043517, 1.2960232456627068, -7.6203490396486115, + -7.170062781547793, 1.4606818503734946, 2.254454243477766, + 0.4888493896618929, 2.445951735545381, 3.130901934841017, + 2.0169064244671624, 0.5781320235978845, 1.164559165113405, + -7.085727391465785, 1.5563134560808463, 2.5246786453408587, + 1.8306790539513156, 2.063158354285914, 2.951222072815112, + -8.011694407902795, 0.6912192194209621, 1.7567867998704312, + 1.227745741829922, -0.15483148523896537, 3.080062309803283, + -7.014075101217134, 1.7153006739574652, 0.42563776715604157, + -0.20460280950116075, 0.08112706131989966, 2.3249243480067583, + 2.8599522371258654, 2.8250697629458648, 1.3263597524146535, + 0.6689904965545804, 1.7211640556971661, 2.664252570995877, + 1.9021155590745604, 1.3039480575116782, 1.6186179551129143, + 0.6994200226046031, -0.2762234251771253, 1.6463651245781266, + 1.714335455602332, 2.863930022411937, 1.5345625659420514, + 1.9874458198165799, 0.6236563963009678, 0.5487365154798838, + -7.699812241244133, 1.9022132491593855, 2.0582611608232324, + -8.241695983493726, -6.6537679124807, 2.1727184060924447, + 0.9273336782436994, -4.084132513497494, -6.170446784167851, + 0.16227905402765097, -6.5818959164282065, 0.3856228859005982, + 1.0640002227515153, -7.938741293583762, 2.093082240549366, -8.7906152886363, + -8.901765187372959, 3.8337110169924444, 2.1154827591984047, + -0.024563247863549253, 2.265518351996009, 1.9006504722937423, + 1.917766167905046, -8.633956025491374, -8.851789595046611, + -0.38659176008223367, -8.87236621013963, -8.501176765733607, + 1.9191111526959272, 2.0092982704073235, -7.981956809324846, + 1.4206166475637727, 0.6387858496083604, -4.240260019432114, + 1.3929661181125392, -8.64662315068952, -7.421202866081349, + 0.007880371938225328, -0.19056302410489345, 0.503120685047802, + 2.1688687868026357, -8.292235911623273, 0.4841239485526286, + -0.21587616980271407, 2.6559586365930166, 0.8458314061382362, + 2.06133046178105, 2.6770161025917525, 2.2054628111229193, + 0.15780246248383983, 1.8897321611408149, 1.1275903344847946, + 0.7875862341118278, 2.1134528176796077, 0.043938642482980586, + 2.215455707867413, -8.456452178054775, -8.692009213476931, + -0.5101357762192221, -4.421699075118912, -8.284672622364882, + -8.836080267171257, 0.2811631865005029, 0.7142526358338925, + -0.30874882508807805, 1.7719153462076291, -7.779768112165598, + -0.2753804205635559, 1.9260020511696359, 0.05227095637109941, + 1.1788794487568979, -6.726659315471383, 1.6706662165839776, + -8.947952635047871, 3.162863553794859, 1.5389964899535564, + 1.2544440603559768, 1.7145010953616646, 0.4822413648004758, + 0.8802826978220544, -6.928476477946392, 0.10778270716980459, + -0.39126373206777293, 0.8622491527567213, 0.31010488292438115, + 2.03192764830168, -8.796503623860978, -7.25126358436173, 0.3351051631162634, + 2.401849776359339, 0.9593991430845032, 0.28888122690848994, + -7.88160986575865, -8.795296799403625, 1.0757305446731973, + 2.1924085737667283, 1.0972505543442912, -0.2774989094254504, + -7.066242301005415, 0.11467791494875802, 1.6091405789212163, + -7.260729719065053, 0.33316620169517214, 2.205281933674402, + 1.172124004482102, 2.4696000397910645, 2.3730224401479516, + 1.3335890617350563, 1.7094335595127936, 0.8208981431645013, + 1.8647377935509077, 0.36747321127457044, -7.060084906231471, + 2.7804890302269643, 2.9671177107298687, -7.505782900572595, + 1.0474434372261008, 2.9724405167414307, -7.635142339082416, + -7.217456677559582, 2.727741118573167, 0.8465807600627744, + 0.7523149050591599, 0.5201613891793713, 1.925880550199435, + 1.9625870722855867, 1.010200439428451, 0.22032048692175552, + 0.7273647588069262, -0.1355918572976582, 1.345341378000972, + 0.5800264441178827, 1.380656425038407, 1.8792469186637635, + -6.514298843285813, 2.099765193816464, -7.509190765310397, + -6.890897830401605, -9.222846612291947, -7.172078812604409, + -7.789712879680477, 1.254734993818503, 0.5531895666629048, + -8.612093971837751, 2.0864710531435913, 0.45494547747797875, + -5.508790997390626, 1.1149993703403722, -8.0440977364811, + 1.6559663293874263, 2.420212513816951, 2.9853181372794784, + 1.515004941287756, 2.547898257908868, -6.622344884313547, 2.279783867318617, + -7.461243943269229, 1.083537216055773, -8.539160423577666, + 2.5671093694551743, 2.5120642770654174, 2.7201046348614373, + -8.83034854050044, 0.40813570966610907, 0.1478548923910506, + 1.378802988881486, -8.145853074840295, 0.5859367793324454, + 1.2685315732446376, 0.5816188712363226, 0.6475648145998375, + -9.170946475716914, 1.1255854211133745, -7.204255242285411, + -6.735249012873698, 2.835288408826582, 1.3975350610213035, + 2.0655171510622794, -7.142744911960321, 2.5084973350342827, + 0.39401025608934637, 0.8413376253131408, -8.22411101126183, + -8.316357387285601, -8.301731394638491, 3.1850216861049936, + 0.31145632933967327, 0.7490086616134807, 0.16499663357513214, + 1.3340694243972384, 1.067740313249043, -8.778641494106067, + 0.5323884586681293, -6.791677941954464, 2.7181197902959324, + -8.120989910120539, -6.566977462156488, 0.19971778956130795, + 1.5142333116934048, 3.049490121824, 1.1362102180694054, 0.388842475083235, + -9.19938011247477, -7.435297148324332, 0.5219091136830705, + 1.6676803894699457, 2.9213805693889197, 0.6423880183415991, + -5.6180731048586905, 3.041626787445567, -6.6873096359841275, + -7.085387574060344, 3.074449590208328, -9.049286753289348, + -0.07955063623519049, 2.547868234063361, -9.028291326562696, + 0.7130986820012628, 2.132638517739885, -9.065414093828675, + -0.021756493080876613, 0.6630241370437974, -8.042827548943682, + 0.12705662340916574, 0.9458870828880522, -0.3662118100714234, + 1.0640708262928484, 0.7090274222032339, 2.7672877694347844, + 2.766279528804059, 0.1334718113791702, 1.11615265120768, 2.6488368076661493, + 2.2412978981691953, 0.12403072980622999, 2.5653841751762845, + 2.46840596735832, 0.7664635895912416, 2.1808954147589534, + 0.7780720929790442, 1.154606096196686, 0.10572028977310916, + 1.2851076877131016, 0.556425323239768, 1.0685018048754145, + 0.7454887942125477, 1.7527547535834673, -7.546222752678161, + 1.3532650448586065, 2.3714247164495292, 1.982143701618346, + 2.618916661184878, 2.640381933720139, -8.385071772460382, + 0.7444984479293888, 1.5068169150034114, 2.2271220796396216, + 2.7368767412298602, 2.417331566583442, 1.1871226601686244, + -6.650805662509953, 1.8867538961050732, -8.809438191940412, + 1.0340198085047216, 0.09741528294006592, 1.1144739131504813, + 3.568290861071225, -8.675318927552368, 0.27057758173492047, + 1.5034740911958426, 0.6576685640069088, -7.970029234276875, + 2.0543143183721093, 2.4976178443593477, 2.592234390534009, + 1.2794420349507243, 1.3280661268357454, -6.1397431101450515, + 0.6493502392033413, 2.451702099349213, 0.3856119997859295, + -7.846337417047921, 2.198060056284684, -6.961349711979518, + 1.7437468720369593, 3.0464861871275026, 2.257505905763807, + 0.30885351917698495, 0.8297613717282993, 1.5747759023875523, + 1.317957570410962, 2.553616904435545, 1.424238444833736, -6.409821252587784, + -3.7121101731513755, -8.07988081118465, 1.1581201368122398, + -8.736322415995028, 0.6153135417031852, 1.1851950640560585, + -8.04273204084384, 0.3753515125893134, 0.6044410800186297, + -0.4462806348390067, 2.4876025235421375, 0.4243786377495357, + 2.397867885817016, 3.042072995902169, -7.042235067429063, + 1.4433894825003244, 1.3503899983375744, 1.9267961475043072, + 0.11303028424955176, 1.2802237387762023, 1.1807097565574458, + -8.396811638245762, 1.966221028236108, 2.670565206957964, 1.941463422585001, + -7.301573843511433, -6.791358138871878, -7.753009533802501, + 2.0725098091559078, 3.3508596926505434, -8.336750014567741, + 1.328999925878136, -7.498577814850508, -6.909957244961768, + 1.6808666342979746, -9.259426955145779, 1.0529248929166835, + -8.659503064520303, 1.0794283442346126, -8.169354608391833, + 1.2687417154610972, -0.05008806804418893, 2.554466483058769, + 2.6463387561425358, 2.0915278486625852, 1.963493051516514, + -0.058111812310782905, -6.719162782261123, 2.1286532096533546, + 2.6711102253818306, 0.8113490399413341, 0.1691688087031465, + 0.7576914618941437, -8.573974536623778, -8.202351570300284, + -5.022030620598906, 0.7378700433168435, -7.896595642041391, + 2.715954389554796, -7.328039581111833, 0.4656709743306232, + 0.38780981951749893, 2.715794355311965, 0.6832808179661064, + 0.8165883110436294, -0.7747965792331853, -8.73586196187189, + 1.4133836545434357, 2.772935925322485, -8.717567004542799, + -7.534740709216023, 2.925460725713395, 2.8751008445351975, + 3.0793788378304163, 2.1533793279196245, 1.7978212944486598, + 0.7107077365239324, 1.0427976193825639, 1.7330570013400586, + 0.00556742814150668, 1.5612831466067632, -6.734421807039429, + 0.4013219184744089, 3.5262979904457143, -8.95170377984456, + 2.2141611432455224, -0.08047619438343041, -5.957196390708477, + 3.3226888221987836, -0.37803085074796233, 2.645414596563064, + -0.33862855976270245, -8.46555558570551, 2.76345646211871, 2.40494295752824, + -6.840982915756616, -0.3242636234143703, 2.7750295264645297, + 1.8183999533967665, -7.678438800179548, 1.0160749550942851, + 1.7137173475535832, 2.8083713130665635, 3.1604421650794694, + -0.4229217013580974, 2.1765062672188935, 1.0311177140396095, + 0.6027953301818604, 3.2893079766983124, -8.419775319138095, + 1.1517915087767054, 3.806484015949818, 1.813709085411365, 1.586889829445234, + 1.0553305281082588, 2.0387604323716473, 0.46255061828788563, + 2.5403778903660448, 0.8978741659153907, 2.9667459702613748, + 1.7935809280277752, 0.9979198425330458, -7.348823524408095, + -8.190100691652388, 1.013482899172069, -8.176589705475472, + -6.776804544087918, 2.5175129624009247, 0.07453293651955747, + 1.1677142732080015, 0.8121530043524006, 1.0728087393996888, + 1.3207866981412948, 1.391487660213971, -7.325262871111656, + 2.480512446508523, -0.6726147334600983, 1.286633878671537, + 1.2848571814950263, -8.630068144410178, 1.641074512334856, + -8.372520390263729, 3.6220477954119166, 1.5476109871904122, + 1.3313072985443402, 0.4509802411964847, -3.676572896300967, + 0.3431658561343909, -7.394169280242893, 1.0111153209989923, + 0.6236978299182561, 3.2232768877654876, 0.9889212142907509, + 0.9557662078999765, -0.16552310968824946, 2.557882614305319, + 3.170986388211581, 0.562007121308636, -0.6890649793533657, + 2.5864702274219007, 3.147873301590315, 1.8452327103988686, 2.2300578670635, + -7.914572431346472, 1.681388435406869, -7.934181576720307, + 1.213953350024886, -7.767409167529324, 0.6125353497428956, + -5.862074779777948, -0.05579432135103433, 1.86187714887813, + -6.831639403701684, -8.368366805004245, 0.7141650842394128, + -7.2296156596447805, 1.9658449157112, 1.203402773136181, 3.151848920524179, + 0.8134834215896044, -0.0015891696015058621, -6.6206322071046335, + 2.442034190696451, 1.4642792894623475, -7.662456653055396, + 0.5578606457466265, 0.4827129085038648, 0.2447768553210342, + 1.2446398205960199, -0.25148268369407345, -7.866482447918518, + -6.778773007540573, 2.364212567590591, -8.876829124962727, + 2.3709111578808897, 2.443004766387172, 0.7629475448244297, + 2.5660739576610623, 1.543324993772585, -7.445412828672346, + 1.3108578718592787, -7.38077750258055, -0.06035745322128779, + -8.065274811827726, 1.3228399598913307, -6.855601930353441, + 0.48550708554397876, -8.118421982992933, 0.47680284185583893, + -7.882497296555905, 1.250031921419141, 1.9815759668868294, + -7.84848669377249, 3.367580290061463, -8.440463565239842, + 3.0765713208166643, 2.047624797367175, 0.4889432739407685, + 2.5096694366000163, 1.5221815582718397, -0.24634193428253054, + 1.9915302143198261, 0.6635624893207551, -7.891419294916788, + 1.5075850215925033, 1.2568996983393395, 2.378860296841117, + 3.1394575024244022, 0.37361594939970977, 0.935152027531952, + 3.047339993260869, -6.773412066573279, 1.0136520227701125, + 1.6683344851535156, 1.3800348556849296, 0.3710586489799465, + -8.01667358521836, 0.990252834741967, -9.126682421524748, + -9.193666922759986, 1.9428961494619439, 3.587663110515121, + -0.2622805993300625, -8.393066513474231, -8.596771623489156, + 2.302138698806313, 2.0258880548889793, 2.6910996993473884, + -0.6734939697369002, 1.04114747684359, 1.718185888051403, 3.48276539461964, + -6.95854436686443, 2.4735697481156858, 2.041149990149579, 0.673791469689127, + 2.9897117569477327, -8.238988517507169, 0.9761093805477352, + 1.8216332855723016, 2.2164179615841872, 0.4932126968317748, + 0.3780496352396801, 2.0649711404519855, -0.3613929635545015, + 1.530645089629263, 2.457243579429912, 0.05440985134375729, + 0.06784140843088526, -0.003004518576022715, -4.447565313413029, + 0.7159244478392003, -7.4391021004275935, -9.10853187457136, + 0.34616954373534803, 0.3874840426360299, -0.32695879149184703, + 0.7751933946282066, 2.9773628087798647, 2.2142437878977925, + 2.1843254988850855, 3.059126414689936, -7.692981165498031, + 0.3024228093713769, 3.605203578070868, 1.4644727704422869, + -8.727072293408847, -8.091615408220388, 0.4629390055507127, + -6.980247924896281, 2.4171511912056944, 0.9091940581067055, + 0.045724673301188894, 3.0929852250357976, 3.198135004353189, + -0.21094478484423296, -8.564324258125765, -8.810215664648535, + -6.815470170564254, 0.9382340965406358, 2.558848589992109, + -6.860407582762542, -0.11677156318837643, 1.7632932116246454, + -0.567984892256506, 1.268764912958375, -6.793588858602195, + 0.44299312590662765, -6.859297675764476, 2.587620793885912, + -6.352486573862255, 1.1729864504462661, 2.340260731160978, + -8.048569125070872, 2.318283003374852, 3.4853185969834053, + -8.250982909735939, -7.642972426754199, 3.2704918520039516, + -7.899950558873467, 1.412053293639085, 2.454183942959644, + -8.471969075893853, 1.8275377932192616, 1.1836780899054724, + 1.3203521358289407, 0.9678677193752282, 0.481491658469547, + 0.8447740588469119, 0.9658229991595761, -0.24011170869178097, + 2.839010771182523, 1.9624349399608014, -8.599242423056895, + 0.4211472361023467, -0.2793320314444414, -8.797108635586614, + 2.9392182781603906, 1.256873152990501, 1.5665471944473703, + 2.6547265873722368, 0.8105761486188217, 1.721884808291741, + -8.234430197275405, 0.5536636270100801, -8.355106987612643, + 3.178140091519325, -7.73626088974614, -7.144415677325785, + -6.691323046710537, 0.18838902967814972, 1.3810650697628872, + -8.528176568166815, 1.8735027217692781, 1.8177810237061083, + 1.8528978825048201, -7.6581702947911285, 0.9851936282135941, + 0.9749140655529156, 3.4804614557444093, -8.271591218158985, + -0.0692916061467144, 0.23636074444602018, 2.2536748103998634, + 0.6620572261158134, 0.5272863441054563, 0.31987648412936154, + 0.7902815603429416, -6.85058804260707, 1.0999584013545434, + 1.859646243461103, -8.559557059496289, 0.8252105446203934, + 1.886734510600049, 1.6134861199944395, -7.985644994531114, + 2.971573949701723, 1.3672364573922098, -0.3682007887540835, + -7.103789187918907, 0.9405168733953734, 3.4871526094460066, + 2.1859096620649496, -0.06289084203356823, -0.10258851143346698, + -0.18803971518510462, 0.8634144021978678, 2.1582894982893395, + -0.4677742138351482, 2.0928793604794955, 1.2878926947686777, + 2.336889592470472, 0.6872067448511159, -7.748766216039927, + 3.097444263728701, 0.5556866987589535, 2.6712301633728353, + 1.1849033710043753, 0.5486668885120461, 1.0907831266305195, + 0.8434242995293644, 2.945520310117043, 2.8605173091238214, 2.19486511424655, + -8.827037046270771, 0.8032457482846421, 2.7703795059818543, + 0.0388776722783144, 1.2645413629366868, 2.1265867903136657, + 2.3385576793976584, 1.917127276522154, 1.0529020988066884, + 2.0148206403888405, -8.191291663926195, -0.12305657129402683, + -0.04938015097326366, 1.3313074227837138, 2.649367557322003, + -0.08737222278800186, 1.8643940520501083, 0.33554885638604737, + -0.10208068750017399, -3.351687711644993, 2.2491187462351876, + -7.264665631287486, 2.468811775400256, 2.236940253230926, + 1.4395837747782287, 0.5756193294246122, 1.566682837365336, + 1.1941344117585693, 0.7864333853514603, -9.130530246586128, + -7.542220059862066, 1.57835349664291, -0.5198230637738277, + 2.367130441925575, -7.508216068087835, 0.3251150387191636, + 0.4305638446644724, 3.576750227255939, 2.926957105266908, + 0.6489723337676349, 2.6600070511561866, 3.0978307529860145, + 2.14332749047063, 0.8417453308787288, -8.362638563146596, + 0.7655484851530803, -7.358857148523173, -8.795863146335122, + 1.7528113987581404, 2.1996806032770424, 1.1842707222509872, + 0.3370356510506722, 1.5657862898662531, 0.9954573129035333, + -8.362659182252077, -8.572523895071708, 0.6623382018746384, + 0.6994445665772647, -8.812671581275692, 0.7069222566198479, + -7.0821163329383, 1.9549163979002904, 2.7673886265006495, 1.58020571085722, + 1.1157305393370385, 1.8192078696921687, -8.648738166417022, + 2.628514031659668, 2.307267931960636, 0.17720288819135216, + 1.7561274604591817, 0.09524221875625612, -9.01315111179075, + 0.6047127666500285, -7.244699265066096, 0.350818800626781, + -6.8329565403043935, 2.2955591146423098, 3.0182115153169815, + 2.3746049023107285, -7.019640140605208, 2.4647840205414395, + 1.3434268505839981, 1.6854086164192068, 2.295861317921914, + 2.2764302909930985, -7.983364933412937, 0.5807929594978267, + -8.894143291256958, 2.9938838722469345, -7.0788633945319415, + 1.2178067680325075, 2.856905931248516, -8.868555023102441, + -8.111576071477934, 0.7355491495970233, -8.884594494490006, + 1.3008471541908617, 2.0846825428565143, 0.940236823123737, + 2.6584950353466343, 2.5762583674418824, 3.3819401974882135, + 3.0910570249281393, 1.2778711559145604, -0.4827457256339073, + 0.8455691575019935, 2.989985556284473, -8.594252280966447, + 1.9197413450145182, -7.46547909931198, 1.6722748789866753, + 2.2138221464125243, -8.270938951734585, 1.7386397987695124, + 1.033678879096028, -8.516503001822748, 0.512090110414948, + 2.0059308250635013, -7.781026228664235, 0.36210339688697013, + 1.8975077592436573, 0.7694797196827183, 2.9175852118329306, + 0.35192891316867225, 2.7464548788808485, 1.8181456629054111, + -8.879105287057802, 2.364591270774948, -8.811648789232835, + 2.2303404870811443, -7.212500783453163, -0.04252695108275349, + -8.27691641027849, 0.17389279156214596, 0.3419299559039324, + 1.1168557615318893, 2.6300729259371325, 0.519545977271745, + 2.026006377830216, 2.4542416541761796, 0.6214882222636962, 2.56545276551517, + 2.371782875552455, -8.410901915894607, -7.755180617297871, + 0.26854433319712717, -0.29016912404990974, 2.7855698716380655, + 0.7031441386051922, 0.6463634663828767, -0.14572491547363256, + 1.0846660011879703, 2.9877269537925093, -7.4014817343606, 1.532485901854579, + 3.2834185214330414, -8.395186846378069, 0.7067177076339348, + 1.790307058312988, 1.9045140645897747, 0.8155319473452132, + 1.558527430207653, -0.4562439874529775, 0.6283683976770774, + 0.3170889013577815, 1.2269672091211687, 0.13239083090554576, + 0.9672200895075614, 2.3228852138079854, -4.508240674846544, + 0.937926825482767, 1.9403937731548746, 2.5476778851631727, + -8.791030377657798, -6.90900624236735, 0.38668188599048714, + -8.387398417504254, -7.344755132587228, -8.401990418987419, + -7.427545106366351, 2.052933392737336, 1.243724639000523, 2.492261060779638, + 0.9113773906922337, -0.15816106323304419, -7.470553956059105, + -8.846441596666375, 2.827116680018038, -7.116712997211687, + 1.2433205851368418, -8.346468787028506, -7.978333067918487, + 1.172963260744282, 0.2608874203114955, -0.46724686695630874, + 1.0564086871641414, 0.06130467277244044, 1.6818877741501426, + 1.318743028841478, 2.8373390653938273, 2.576615766795672, + 1.2681807565928347, 1.4580249782652615, -6.524433867154633, + 0.09581451622485024, 1.8231985588689075, -7.358029518015586, + 3.511196746259249, 1.8394281143396174, -0.6754116281933468, + -0.020197099799179743, 2.1780440921947566, -7.409891359292506, + 1.052901385861119, 1.2241086946853335, 0.3665532298720331, + 0.14478725159505287, -8.151941019411806, -6.704773956752906, + -6.115756625251118, -6.974690256772126, 2.0210836961226892, + -9.015001772676642, 0.2646431501384486, 1.6940258171839286, + -0.2610635405056007, 1.7344415107250657, 2.4462330102590086, + -7.068860147884828, 0.08695837348604589, 1.8701982293321116, + 1.0504262384847716, 0.019527985748346775, 0.5097245787288074, + 0.2389915874027862, -0.19218159389880246, -8.855488867463228, + 0.6020616642969194, -8.09265510730711, 1.3150371364975184, + 1.4759405666726864, 0.6125503265197201, 1.0338508449971633, + 0.8355074008305553, 1.5657388390288403, 0.19060171190029251, + 1.9216391475271553, -8.552212424405148, -0.10872450136022829, + 1.5803257663654455, -8.312807240378005, 0.19254420609740558, + 1.5921086618162703, 3.0724652883798753, 3.119585347470178, + 2.3680946054804948, -8.996751873936851, 0.5450779135596553, + 0.3631979793991185, -0.08367913106684004, 1.523933920210135, + 1.9337098908579557, 1.618362115241489, -0.2920987527409687, + -0.08027388569056067, -8.473382618231554, -7.768478821668898, + -7.782876606094697, 0.12206627215748748, -8.662712369595276, + 0.7044770310142159, 1.2240212148539857, -6.580456328124205, + 1.0167328126861905, 2.898843091197227, 0.587714076153449, + 0.6216570749055097, 1.0414748533858058, -9.219472775085773, + 2.2001939905709453, 2.094708624460661, 1.746527945940157, 3.03051313566259, + -7.249968841919131, 1.3408108007543746, -8.166942766681114, + 0.979736597403027, -7.324885568806586, 2.6278233426622917, + 2.854107404015036, -8.315196696814988, 1.64949805448383, 0.9702802532651041, + 0.7306766790583936, 0.5492725402351939, 0.9757266772327314, + 0.5017028463917943, 3.1800094770093223, -9.145099532522584, + 0.5049374526866867, 1.386725096088461, 1.3587664430780686, + -7.140336167363484, 1.8245134915391863, 2.073295079791952, + 0.751375960285473, -7.606091978393865, 2.0767323624294556, + 1.6065306443491023, 3.235065720540448, -8.721850121309014, + 0.7196711904884685, 0.9816788132475567, -8.84696255216795, + 2.626809215666006, 2.549815866941008, -8.911171932324867, + 0.9509628399304939, -0.23927259256889213, -3.875366962750523, + 1.3908433382198686, 1.8916021423621145, 0.7357495578652032, + 1.8923717026364686, 0.3266032798067937, 2.300474414349679, + 1.5890325507701302, -0.06549343928613015, -7.538525770096769, + 2.318466047257237, 2.8665125668115454, -8.153893833561344, + 2.376837200867359, 1.4709715498404656, -7.706214252240921, + 2.740327301519449, 0.09028636054530002, 3.228455947564836, + 0.5513794682867488, -7.295604836083069, -7.759906957734117, + -8.09777432729763, -8.756864903683306, 1.2763511405271517, + 2.945562275839741, 1.3838398593194638, 2.6854401964823555, + 1.656261678163789, 1.7533428744601358, 1.3611257362588403, + -8.655329830508306, 1.2443715368140775, -0.1609367996719012, + 0.4399722778070814, 1.4550332512164776, -8.299697577767187, + -6.791177821351162, -7.296317217122517, -4.24043076076241, + 1.9744461728026013, 3.0169108659129678, 2.085481071313922, + 1.5796231665236808, 0.28883706586254004, -7.591695100980768, + 0.6925641152794203, -9.11235095395525, -0.2735603783775178, + 1.1818571609991912, -0.018031404946787462, -8.419312407491887, + -6.567851485538858, 1.025406857208014, 0.9351698697703867, + 1.818433527458495, 2.572785712333763, -0.17393935498240165, + -9.016630101374009, 3.2792795030834743, 0.6658242879271989, + -4.152270499925638, -8.157087288303547, 0.335924182306347, + 0.9271775190846979, -0.03618409014146321, 1.479665880222401, + 3.3166424655428544, -6.576355835404252, -8.394098885439393, + -8.303510483979204, 0.9062729084027537, 0.899839531830259, + 1.8193688012574165, 1.4364119637784045, -8.767490172955053, + -8.595866558481568, 2.894212712135655, 3.0533541874355197, + 1.476114993804659, -0.6692909143542188, -7.138202852784044, + 0.21695706225651779, -5.7962601631962904, 3.7264192571904973, + 1.0442589644292544, -7.076269965204877, 1.367915964860723, + -7.544790546463144, 1.266952685212199, -7.804861505331333, + 0.47349039096221374, 1.5930269805126527, 2.5782435864991484, + -8.074721153378004, 3.5025819239037292, 2.9573712662329408, + -8.193982940881433, 3.2661504885678805, -8.948840147357354, + 0.6610691084305056, 2.6835411548086467, -8.934693065916505, + 2.10816139136865, -7.548985911968935, 2.4765230790798833, + 2.4141491397851342, 2.739887738696199, 1.1338375590537584, + -7.31405143327513, 1.869248007035211, 2.1401939557341008, + 1.2329394233202717, -6.723686979858944, 2.258413389809931, + -8.768330194156949, 1.2589709754909724, -0.3036390540432826, + 1.9527663384310978, 1.9649532855712855, -7.981643134186547, + 0.8111442705420386, -8.775732723411297, 1.2730604738899645, + -0.22849125581746754, 1.5137214298375352, -0.5539006361886138, + -6.960063658385964, -3.89830422876073, 2.8616026407122552, + 2.9130500271371296, -6.828704833371259, 1.0667775059630333, + 1.151566623944205, -8.838089952827328, 2.2104783974902467, + -7.902865224549581, -8.302070760649276, 0.5350976393159605, + -6.716064221510766, 1.267120489241334, 0.6953533727748282, + -8.502301241872468, 1.5904998311089247, 0.8035782114725972, + 0.4045367467954588, -0.08084644425017389, 3.1042891336787104, + -0.39528854294041516, 0.568607566886694, 3.2746664864400366, + 0.1352387754209979, -0.43424640761761435, -8.46713488994006, + -3.400403057005808, -6.655886343018463, -7.836082067870872, + 1.4006280436181675, 1.8310149135386509, -0.2144436816897158, + -7.662535451019991, -0.28366331573350656, 3.6834853049456493, + -2.8908696938583747, -9.092271857083439, -0.129077551303571, + 0.3467097889851762, 0.19864145631650879, 2.628033215265815 ], [ - 2.26612718696679, - 7.877304234882818, - -0.2448122627872643, - 4.516540904583949, - -4.185123130466475, - -0.3563651520223698, - -0.8099006227273609, - -0.7273773022983425, - -1.0774494744803462, - 3.3295276863355623, - 8.016118846675909, - 1.566371903855566, - 2.527331443604742, - 6.0204023210462285, - -1.2725524662708634, - 1.6069492541685462, - 5.49339016416923, - -0.14877824811217932, - 7.541563678570806, - 7.828715198686858, - 8.78143506494612, - 3.0724004942655743, - 6.910282329799579, - 8.520562682219973, - 3.034769667067511, - 1.9556477732053121, - 1.391521150600587, - 3.4951871559764998, - -0.17956672474858976, - 2.26349058202461, - -0.5435329290392841, - 8.741637845270487, - 6.471130230045931, - 0.4137720216823771, - 5.314452356601059, - 2.6065034944063608, - 6.069220385698501, - 3.3364078398310455, - 3.328331508170648, - -3.3524926199567573, - -1.435579284246872, - -0.9751170795016273, - 2.0364383183517596, - 1.960212653802774, - 0.7864521202540135, - 0.5657911702861587, - 3.092853905227683, - 5.01806876941713, - 3.8663921379199855, - 2.821039512684959, - 4.622541969701707, - 2.9858484817831323, - 3.6261134085537847, - 1.1724037712799356, - 1.3838290511047608, - 8.806048701083698, - 5.668478923267121, - 0.8018037690672242, - 5.142631152815043, - 5.162406058696506, - 2.6062536456732297, - 3.2943461105091645, - -4.990164104959657, - 3.806517214224376, - 1.8949308089289694, - 3.6353370033600987, - -0.27148904339677543, - 2.7380806442893926, - 3.006631409999392, - 2.0071121263434377, - 0.04628078340754096, - -5.1377197960285175, - 1.0483368306122867, - -4.784796367966544, - 1.5862439101500176, - 8.756330051078708, - 1.5805286130098075, - 1.7098684717663246, - 3.200383653069714, - 6.709460319064008, - 6.307911810299551, - -1.739665781844903, - 4.245169768183147, - 1.666455373730062, - 6.837709319524681, - 8.3481618163966, - 2.9875858571030065, - 2.8139839176386436, - 9.099261178847472, - 8.948801052040421, - 2.006202530800494, - 6.73880301635272, - 8.17611168200775, - 8.773745685376184, - 5.91600439185124, - 6.104433949863836, - 3.7052400992485914, - 6.192779846035659, - 6.600091346107618, - 5.923022741981018, - -5.250204433842824, - 5.223817204947422, - 0.696206808198047, - -2.9769151747495926, - -4.130522494380668, - 7.584957421710554, - -1.5598149353078123, - 7.718639481716779, - 3.0013319833107084, - 5.928077111182149, - 5.152861273092454, - 0.9286834020630569, - 1.15570293124766, - -0.11413301755132071, - 5.3564497446505275, - 3.8928146168617306, - 2.967358817084032, - 9.258863388399549, - 3.629272759041251, - 1.6426518374793857, - -2.8569863552591284, - 6.781260075162287, - 7.624208895126389, - -2.251232030343179, - 0.46027511263626997, - 2.1982523757635377, - 4.5679304243381935, - 7.908571146138121, - -4.853529006657921, - 1.5476649669885307, - 0.8422206760808629, - 3.314306441122399, - 1.435163153918387, - -1.729483134322791, - 9.254698656553444, - 4.161313073939071, - -0.19285497459513173, - 1.471278108190918, - 0.1733342761260208, - 9.03087243734635, - 3.4629830189459407, - -2.6264808461106277, - -4.71657716085353, - 7.869469706260304, - -2.620405496749864, - -1.578270511956123, - 8.357815415289556, - 2.752648283396273, - 5.565302741704507, - -4.805089857063229, - -2.1885042710137363, - 2.0585183776678355, - 1.1610136154324948, - 1.4912027874169376, - 5.914379471375557, - 1.3499504765324346, - 2.044807431029458, - -5.406212771764639, - -2.521892586706258, - 6.1418606819986445, - 8.415457501107205, - 5.604133372216368, - 9.143496250718814, - 7.319575349089649, - -2.06421150615848, - 8.215989933714578, - 1.6857886508980149, - -1.0878353251562816, - -1.5829661285262637, - 1.4674923894311405, - 2.7741856684983164, - 0.9185064155989479, - 1.2781037230916843, - 6.884473682406043, - 0.2934983262573301, - 5.785360809322976, - 2.453893016522862, - -0.7453305767736639, - 8.396234722381891, - 9.850354025725204, - 2.216365887386976, - 8.431236102153253, - 3.3932288637112924, - 3.6608661914291054, - 6.6026731099986815, - -4.953410384187296, - -4.4383215629895725, - 0.07462075161455901, - 5.919009879800911, - 2.95366980628499, - 9.444938044811291, - 0.9076977968117299, - 8.586093101374825, - -2.947154691692993, - -4.633162015997375, - -1.6398464357794498, - -1.2357874214259623, - -5.298383006143634, - -0.43896349898626935, - -2.3401534496139194, - 5.210537676425541, - -2.299537704354067, - -1.1292417029652433, - 1.5799175742083458, - -0.336520751004366, - 4.223746594866309, - 2.8317988965614815, - 1.8947275849516294, - -1.67358278514923, - -5.253236405380462, - 2.219133984219187, - -2.1880534239704144, - -1.3375574851781555, - -1.6072610776058833, - 1.5397232688385492, - 7.036819843042076, - 6.692937873958802, - 1.082746220482573, - 7.797508199429759, - 1.2007123936245745, - 1.8770497605398146, - 6.8994754889657735, - 0.3012191088043153, - 1.068935678724868, - 3.8501454879447587, - 1.7790542501409592, - 1.9614894543599724, - -2.3388476137009833, - 3.110452608712005, - 2.488897512781782, - 0.29446492568337673, - 9.228134471260587, - 3.063679541623608, - 3.127534142642514, - 7.2918077503859715, - 2.1074622260198823, - 0.03666378061265447, - 2.348354665889141, - -2.776578577073148, - 2.5981465208878927, - 1.9166047514477609, - 9.467577997348005, - 5.157166112164271, - 2.7420707192882334, - 0.589056280377641, - 6.296664749024959, - 0.9971281607317918, - 5.968437263241744, - 1.0571690485567766, - 8.746282612307349, - 0.34173616693893566, - 5.460155699051275, - -0.33199671017021387, - 8.506589166854504, - 4.760513163928613, - 3.9122175258157936, - 1.819189742944049, - 9.482487935152745, - 7.768142046743971, - 2.778312560578788, - 0.8924815069256471, - 0.5781476976836171, - 0.879392015766445, - -1.2513183283229647, - 2.9135625658416435, - -5.218754075977553, - 5.869987475209426, - 6.215557257640273, - 3.7965216268335875, - -3.978376269047853, - 0.6441282455417816, - 3.195727870886227, - 7.56439441284703, - 3.385762283468298, - -0.24603155345912425, - 7.62699568971826, - 3.095762191436015, - 5.973306919254448, - 2.2140268056041097, - 1.1127192954394922, - 9.6943693980643, - 7.492005482707253, - -3.6717161892789565, - 6.318002419686285, - 0.07016674311514137, - 1.6940972871714632, - -0.08558940895614194, - -3.8815121919455793, - 9.249512566645945, - 4.598958709603496, - 6.177639401450066, - 2.158306022736798, - 1.6740916570728577, - 3.2165428053675784, - 2.139437242413739, - 8.527661461666613, - -3.1283742405260058, - 3.0533838621473004, - 2.8169855715416996, - -5.02273058607592, - -5.114225383806405, - 2.7643256614152265, - 5.972647138843313, - 8.896241804531897, - 0.8767719229947301, - 0.5510963795699688, - 2.0798971261268364, - -0.20474346020074016, - -2.6385424632674277, - 3.0197194877796796, - -1.6532785804244121, - 7.350061942234777, - 8.424823833262176, - 8.59104964106905, - -0.11483904098985327, - 1.3641616272742318, - 0.9584917078748736, - 9.580245305611498, - 0.7483599943956905, - 4.655927249095971, - 0.900799899593537, - 6.2130604458748, - 4.445533750316594, - -3.932854365326212, - 5.551721373679071, - 8.407643877761046, - 5.885232771171051, - 2.4313967402599874, - 3.669780715212272, - -4.904065807718558, - 1.0158008170609327, - -1.6272293048652275, - 2.845528271618909, - 2.807947902007598, - -2.1459588093206796, - 5.608674291803838, - -4.561053175109312, - 7.69017878292755, - 4.905071561851479, - 1.3413222347068192, - -1.1824406687276312, - 6.738801169688746, - 0.9426274806618206, - 0.6751144483531506, - 2.5848520669007238, - 2.1630373426657936, - -2.7076800307547133, - 1.864371841092596, - -1.9682191074896516, - 3.4172413227955696, - 0.020744702897102174, - 9.769505400367716, - 5.798720665320329, - 0.10253613057523274, - 6.0749341819718214, - 5.357902585098012, - 2.4046800092407876, - 3.512704197882585, - 1.29949383757325, - -2.356963075208514, - 3.1765333049669566, - 7.959069530307456, - -1.966846171005304, - -4.25330821080038, - -4.9219589292228685, - -2.197056092175947, - 7.616489594588331, - 6.040817035671559, - 1.8018917838550688, - 3.5407913971559943, - 5.7890179781018425, - 3.5262942067172984, - 1.9950824464659818, - -1.2893474491122634, - -4.63882900188689, - 2.6694949944379345, - 9.674111224668177, - 8.667295005270228, - 5.737081498597616, - 0.4107629657054798, - 3.877046863822763, - 6.0243859744065915, - 1.8838291584410343, - 2.2562445930114294, - 5.4540041564283, - 8.274269306597581, - 1.2052437166236634, - 6.009785777223097, - -4.383503344244362, - 8.656175590418812, - 0.3181436886883143, - 3.1680255522231233, - 0.6533605734315873, - -2.0973750071005584, - 1.994294615835681, - 3.2127097033396788, - 3.439095899977053, - 7.2040540626614, - 6.785366464604335, - 1.9671587153234735, - -1.5827704027494358, - 0.2878181187329489, - 8.701213078576167, - 5.775702232264342, - 3.796888482981822, - -2.2656130867226323, - 3.3040363272429416, - 7.8336984140783645, - 9.341343078834914, - 0.8594581274173383, - 5.3238697665732495, - 7.72383488521013, - 2.0805761896462105, - 5.00590427740257, - 2.4523488846181003, - 1.530253353729973, - 2.2370825976050397, - 1.660862575032461, - -2.2119403145718572, - 8.457984430510653, - -4.738004795759159, - 0.4176833442710331, - 8.521874684509584, - -1.6000253603261758, - 6.170469016612993, - 5.183781673399163, - 9.17207654732024, - 8.7802004157023, - 3.315232146309697, - 1.7255707001482075, - 5.615285248049787, - 6.452463946699582, - -4.925951924112487, - 2.882800800278358, - 3.93467062640467, - 1.8659188085616192, - 0.3306654617084946, - 5.88741276107328, - 2.550510994085204, - 1.3678259326902338, - 8.663112992818656, - 7.745060334809355, - 0.2809562613068918, - 5.757109520649999, - -1.762138015439035, - 2.8786271321357484, - 1.5474645624637917, - -2.261619052143985, - 0.46857555701517345, - 2.5125424778036147, - 2.672966408932212, - 1.816597263740069, - 2.340187280432554, - 3.634287582524317, - 7.989955726847132, - -4.1380036275031475, - 2.657718947754817, - 0.013787158369857909, - 3.3229210110695737, - -4.201062825692139, - 0.6624903490617761, - 0.6944889704349064, - 2.3533513425377217, - 3.7656997519365882, - 1.788749981152106, - 0.7204561771404412, - 0.5730477522205016, - 5.847178671138482, - 2.8793680686193746, - 0.7398060516511077, - 3.4301937342836974, - 2.531013519887129, - 4.755796561060134, - 0.03385492782234758, - 2.0252506551361464, - 1.6234611019159673, - 1.228843641458273, - -2.1668553315537094, - 7.900290985046659, - 2.7050616439468067, - 3.0006973624200683, - -2.1759904645467083, - 1.5375916476358278, - -0.2253952541126304, - 3.343969551234012, - 2.8107101876639935, - 1.0346932550959453, - -3.6532774566258266, - 8.814079961490908, - -5.097909229812539, - 1.2520930353511095, - -1.2672246839647656, - 2.293286603007841, - 0.2410596637437222, - 2.4817504139530056, - 2.248527285829585, - -5.447774337207916, - 2.5923894677692516, - -1.6454701766763544, - -2.430822876606998, - 1.457649746056256, - 0.7661499751857752, - 6.0009153574611185, - 0.1712479024293902, - 9.530954997711033, - 4.983304885063888, - -1.8163769564966774, - 4.880132622934018, - 8.63294213048147, - -1.7947779683144798, - 3.8634935719553365, - -0.8598586499831854, - 1.7046802605527513, - 8.229281772842395, - 5.5246578628586045, - 5.398118716576608, - 1.5665377764811041, - 0.4245517342194059, - 0.42220229215306493, - -4.167833021757446, - 8.930094781851475, - -0.35446000339359723, - 2.0690947296225084, - 2.2632723564752517, - 2.278629737720776, - 8.756058383175949, - -2.384089444260743, - -1.438680090544982, - 4.019783025134954, - 2.770246387450514, - 1.8829131809196227, - -4.477963763370143, - 0.32452313825904894, - -0.21195692236210456, - -2.161747413311612, - -0.1104742560807789, - 2.731352200053975, - 0.13773536558903318, - 1.7722498157924262, - -0.19267629049184617, - 5.9428729939902, - 3.1430293610074944, - 3.722242795519652, - -2.1106747591923156, - 1.0177343680607016, - 2.3476469900890904, - 1.3611397625517598, - 0.5769222962931847, - 6.296183309833097, - 1.1314346686866923, - 6.996354905775925, - -0.49731034627470605, - 1.6514206933772515, - 6.520507562296869, - -2.4876418860943246, - 2.2307122674056097, - 1.2381767470195828, - -2.41036271414792, - 2.8954645460727777, - -3.2678317085548385, - 1.0575729842665866, - 8.232678699212576, - 2.4739770514016617, - 6.4903251593467965, - 0.9560520936909322, - 2.1733654915775573, - 1.7088617486581057, - 0.768606455869161, - -0.18151377978512884, - 9.302470491788773, - 2.9242421348918497, - -0.21070765493454563, - 8.523457662651651, - 1.678976168232762, - 0.4907273484125949, - 5.294112902913152, - 0.9570337069921794, - 6.309717848572128, - 5.853969411321018, - -1.3623712064374873, - 5.889476548951992, - 5.9315557030842285, - 0.9762018475430272, - 6.3787887818601385, - 3.702617423313039, - -0.4259287963564401, - 3.3940136837773305, - 6.33254888740099, - 7.22386178996473, - 9.48026934550518, - 7.942085137181178, - 6.426147842502401, - 6.193095220350733, - 4.7154873457616215, - -4.929461685703354, - 0.40851879820326237, - 1.0355585657555777, - 9.311049935380138, - 1.9601546187502212, - 0.8503197268897879, - 6.417658240356214, - 5.596080884732174, - 0.10266942032352865, - 1.979006093526083, - 2.0923008866853228, - 4.450351856234537, - 1.9178224408715299, - 6.065730723024631, - -2.1405682647230044, - 3.556202577526532, - 2.1423103843101505, - 2.5180534174094977, - 2.221808263874568, - 1.3245232660550748, - 2.846493012934731, - 0.8640007518413745, - 5.815377980880926, - 6.8076746368586845, - 3.212876640337127, - 0.6620465641915558, - 2.8358557130032866, - 5.905823174293553, - 3.0122412380018124, - 0.6042312258565233, - 2.7189140793266566, - -1.6466964841111296, - -1.433601831253046, - 1.7738882086077163, - 8.874211341294819, - 0.6374919565889643, - -2.250631300713733, - 8.398314862302222, - 3.109991448596508, - -0.10447829604288518, - 4.7465579152728905, - 2.450563286997713, - -5.3495016911775926, - 8.243966840080844, - 9.353859126160001, - 8.779407481837953, - 9.625349294803156, - -1.1690780188806251, - 6.883270495069991, - 3.420071073653294, - -2.7124407552557543, - 2.431871694876404, - 8.169142653739367, - 0.10312628339127165, - 3.1747240309485587, - 7.605851681417775, - 6.778454276450802, - -0.33823536051106673, - 9.159816946971777, - 3.009476478092635, - 2.2639212699097904, - 1.9662337900276088, - 5.456163902180738, - 6.2728300525670555, - 6.046612146481042, - 5.6254154012391755, - 1.7448738576169487, - 8.702308099646093, - 2.934366073684294, - 7.210872628959229, - 5.892411059521462, - 5.08227461046624, - -1.7395127801589216, - 0.1317231915653626, - 1.3125074882009866, - 3.0260692912174343, - 0.9616394687550338, - 1.0133611506450468, - 4.889654943041665, - -0.9629338146674636, - -2.4724254857034027, - -5.456164226742061, - -1.0820298779937545, - 1.5859048729025889, - -2.803255229805306, - 8.563567374075099, - 8.004869380926394, - 7.789872652488633, - -5.178475355138235, - 9.00872844603491, - 4.1139580524028085, - 0.8012152195681193, - 2.9547142410904255, - 9.368726650392437, - 2.573308753297779, - 0.8721362717477031, - -4.518618928892753, - 3.038737898072484, - 3.494236477379651, - 1.7802679565870878, - 1.8305970064035781, - -4.721803051184619, - 5.4894357947523185, - 9.024945875104052, - 0.33248042116655596, - 8.978545880756572, - 0.8265498387088497, - 5.253669495716501, - 7.7831176744839246, - 0.13285521333224828, - 1.962292141861213, - 6.457116157100644, - 5.325750037176592, - 5.080589681950436, - 0.9492611156552451, - 8.370070015424393, - 3.7195662602507493, - 2.306501093822457, - -1.943000191988212, - 8.935275055211779, - 0.4523697013583989, - -3.776936478186719, - 8.525555483994319, - -4.612421394543514, - 1.382647763042897, - 1.1862068046882155, - 3.502817236032331, - 1.3690705190155288, - 5.794610055631808, - -0.9857006762062972, - 5.062053934761011, - 1.6804265993382794, - 0.46795210451425295, - 5.91865159008816, - -3.274753687313677, - 7.117602921781142, - 1.1929818334326139, - 0.7770110791675934, - 5.987436755285214, - 0.6581091618990716, - 0.22582897088511306, - -4.02472552189992, - -3.281325205464603, - -0.6180917569514581, - 6.92089529271475, - 4.147765423783696, - 3.889305189579335, - 0.3056958065777463, - 3.4624723766970944, - -0.310507442372391, - 0.8709343758066993, - 5.575731062495118, - -3.9981833864785656, - -0.021001128775697733, - 6.105224149146419, - 3.198468413659969, - 5.394911906600809, - 2.5417900288708477, - -0.8225464773786691, - 1.9292366115723005, - 2.580419662349196, - 1.4624693592572309, - 0.5847068525339708, - 1.292978687785169, - 2.5908710486444897, - 3.348522105080629, - 5.70882232007594, - 2.526697142258413, - 2.8387534278746305, - 8.926971356284202, - 8.826907454040457, - 8.732591313237428, - 5.670388913071506, - 1.181592394821869, - 1.2455224165480927, - 2.612553991589734, - 0.49924191048675853, - 3.0163431566816477, - 1.2389425711694886, - -3.454256812240126, - 2.541300376969366, - 1.1855211805598396, - 3.919987236532716, - 3.108104199692774, - 6.761561693459247, - 1.6617163362455774, - 7.988216917362715, - -3.7069269200955604, - 1.8956754945791268, - 6.513191358838873, - 3.0160456028606513, - 2.556900557970246, - 5.794776377613141, - 2.8913461749272518, - 0.5584477187851367, - 5.823652757914274, - 6.652661373779732, - 2.895484766286893, - 0.004865004026195168, - 3.7362302042851407, - 5.1590787450811115, - -3.2477231320830846, - 5.160237785597462, - -0.0019050703376409799, - 4.6657067577511215, - 2.533925071913782, - 7.49038147862633, - 9.234610799969083, - 2.8091581370951944, - -3.0852521411396947, - 3.8404146939567805, - -1.7364762360283625, - -0.06075348821321888, - 7.855533253661598, - -4.606191298490445, - 8.930715901769902, - 6.433824620680145, - 5.023330657133031, - 7.176348684385988, - 1.5979034036313131, - -3.8353239436016064, - 1.9302760105322174, - 0.4906948818786122, - 0.8236304101051184, - -3.808384325093473, - -3.0486518743757527, - 1.950339059255233, - 2.8772324445470883, - 5.748787174063801, - 4.506554717027688, - 3.3188306684877382, - -0.39989321009171214, - -1.5738329587862223, - 0.8952788762998415, - 2.137591708106581, - 0.9465115280495907, - 0.05176049572996668, - 2.649712588418019, - 6.594377339599191, - -0.6593129867093952, - 3.4751822144088056, - 1.4732219752230908, - 5.704914737143688, - -2.0579211773330077, - 0.6241604121733543, - 3.5941317673956266, - 2.2980594307532347, - -3.9327004047025476, - 3.2251181402296454, - -0.8913391361706277, - -2.7466344743809117, - 1.6619318036068254, - -1.0500979205665155, - -3.0351188482866753, - -2.817952849035236, - 8.918295682184953, - 3.060364669625106, - -2.655530445833815, - 0.641848597267752, - -1.9681102112267448, - 8.525813146195036, - 1.4343982755532703, - 8.908466876353918, - 8.590443320024665, - 2.711023131254724, - 8.89947385113805, - 2.0939160057034907, - 2.65103084662334, - 1.4626356674124337, - -3.208343456221911, - -3.394173167006077, - 1.932850927448628, - 8.805758171186842, - 2.1243490534911382, - 9.028296832464864, - 8.937647726199716, - -2.676577582815389, - 5.903288211290661, - 0.6846977509561695, - 3.8156052421272375, - 0.7634478610334001, - 1.0540467411943064, - 9.699583427222773, - -2.3747586336050936, - -0.95596567080788, - 3.4920439930271123, - 3.11235139509691, - 0.9378696639670594, - 3.35621409897869, - 3.679262467886785, - 3.2029311363539437, - 0.8203047778014468, - 8.554043310004833, - -0.42993598576078784, - 2.511692309884933, - -4.756775876827685, - 2.0603485204111323, - -5.337213657671816, - 0.41725336047678596, - 6.629983319214528, - 0.8903099477880994, - 6.183510404022067, - 0.27046258864924877, - 2.8507973745983386, - 5.953930731914141, - 6.667463064136371, - -1.1853152943830194, - 0.10929547791890014, - 5.159454256150641, - 0.9575382360439176, - 1.0472819291348658, - -4.478812598974675, - 1.63438677088275, - 1.3966105306914227, - 5.436410376920915, - 0.3892766858938439, - -2.2905961508012016, - 5.229602809963853, - -4.864452941250325, - -1.0538101708637058, - 7.164793904682805, - 1.566138730677346, - 0.02704482509077386, - 0.7886677241533953, - 3.979684289364822, - 8.562397301181349, - 9.285407951263371, - 2.0223634080105914, - 0.6748346443384347, - 4.836315638695997, - 1.9106703975216532, - 0.5866544286142371, - 7.697482947447593, - 9.036618052460097, - -3.3937610246659538, - 1.4695633885567845, - 9.806593022345849, - 2.803053620065441, - 2.79080811918104, - 9.085897942228886, - 0.20786152462408714, - 4.554414906944457, - 2.2687730874822374, - -4.4758778295507735, - 3.01749403025241, - 7.009051356750071, - 3.301496781305262, - 1.5978822792179508, - 3.507883946533327, - 2.475904595046087, - 4.723309718269045, - 1.2999810793281195, - 2.6994776633835635, - 2.1776105906692953, - 5.636269224455179, - 9.227390068887006, - 1.6653064746540052, - 2.531245644163319, - -4.796726394177121, - -4.696260149586186, - 2.360303171044659, - 4.809360672005284, - 6.792224681851225, - 5.0239174109239295, - 9.758115953321388, - 1.7938014075697666, - 0.5624509627239803, - 9.136243614649574, - 3.355605586871464, - 1.5306096828306694, - 8.536995394913296, - 4.284406786162418, - 9.288709095420277, - -5.409560336785602, - 2.964373643784957, - 3.7541139426875, - 0.07436249434529059, - 2.6543557259993937, - 7.326068587028396, - 2.361487178667938, - 6.089912059689269, - 2.3291514353075016, - -2.5797469891430884, - -2.204272569458718, - 1.5814138070450303, - 6.603394036525644, - 7.97166923117362, - -5.421796406778391, - 2.310834537661771, - 3.83348926088483, - 5.924444956089124, - 5.705844596614569, - 0.14904642961421793, - 3.2627918032804986, - 9.156346620095126, - 2.3018313060026943, - 2.871420436775351, - 1.748071777193481, - -2.1699630188713317, - -4.423588831601064, - -1.752210329525351, - -2.3332531026084373, - 8.078537148930103, - 1.7468782968550507, - 3.870771091266975, - 9.570067082920405, - 6.532531074910839, - 5.312720960762101, - -3.3929967864383554, - 7.086090345521071, - 6.218945608429214, - 1.8768890922016566, - 2.607564369570601, - 2.7622849353834233, - -2.5914874773514547, - 8.198193747137957, - 2.989820306813261, - 1.7633582516145228, - 2.9524698537504466, - 2.9608279326797815, - 5.159943485109591, - 2.258405427983319, - 3.3374602636934623, - 3.0273792858264996, - 3.1487351190544213, - -2.4495969677949208, - 5.929783834857964, - 6.711771007305786, - 2.081925344296031, - 5.877244018303804, - 8.886653410012418, - 0.6264009865824708, - 1.114324963535137, - 5.582000655882144, - 0.10484985819812484, - 3.9844989239986037, - 7.045339331126441, - 7.376022206417836, - 1.237898376943498, - 1.7470287460799372, - 8.605965387841337, - 9.617446675860762, - 6.882498231126236, - 1.9704705198454397, - 6.000954757287207, - 8.630755642486054, - 0.4865847848937903, - 0.5890115071805289, - 1.4217583119146444, - 0.5759370890401244, - -0.9918362868258609, - 8.505381270758573, - 5.205225724209531, - -0.1641339289559732, - 4.271545367645099, - 8.773787765364231, - 2.8341861182864894, - 6.291040395037355, - 5.433244854956153, - 5.102936340570758, - 8.422552614349282, - 2.8196855273663104, - 5.678926500302951, - -0.5383477536287377, - 9.4253523750977, - -0.22856265846694768, - 5.45239998827267, - 6.874084499868811, - -0.18137759959854494, - 9.478295589662668, - 3.431633175563881, - 2.643320466978511, - 8.186081903820728, - 1.1989638010195498, - 8.54718584644179, - 6.557128513378248, - 1.2300152894799241, - 4.51921956332824, - 0.5693115943422644, - 7.553359478391619, - 2.893921560929296, - -0.7541870943606744, - 3.4344316370472177, - 4.4779116179245815, - 5.302441643354457, - -2.439565181008059, - 9.512899428908435, - 5.385826259956362, - 5.908299075924965, - 2.100513563369361, - 3.3266700309599027, - 8.089733332102341, - -2.6243622656468855, - 7.230528970232492, - -1.0218346404298337, - 2.5739332556555383, - 2.4854245355736633, - 6.832761487018405, - -1.5149844127528729, - 0.9201408348610742, - 2.1035468063646627, - 0.6368115250012512, - 8.214982113070004, - 8.918916811304616, - 2.7106941171332286, - 3.8123959687632794, - 1.9182183558652177, - 3.3011590899178067, - -4.268458134039248, - 4.1607923908684805, - 2.5607637404629346, - 2.537623329117577, - 6.203676444622138, - 3.2449911641283866, - -1.4863704718561914, - 2.0914264281124773, - 8.866073437504284, - 6.360534894196076, - 1.8548388788418777, - 8.546565459118982, - 3.8121042191991363, - 1.782761627693268, - 8.19409331440138, - 7.271377077104276, - 6.713834371576997, - 4.7054015736273005, - 0.6900279581442493, - -1.9950523194654137, - 0.5019672047701859, - -2.4425971792925014, - 8.397284515101749, - 8.274477379414355, - 4.320281308205884, - 2.7306208965349557, - 1.0268803986720851, - 8.041844717647683, - -4.865558143399747, - -4.43090033274667, - 2.080138753512541, - 0.3985237911488679, - 0.13915356157220796, - -0.6797187918311256, - 1.499451661991291, - 3.1062195316504724, - 1.534350188556406, - -0.42490380560179697, - -0.8824812983295844, - 6.137019298389204, - -2.442387086532495, - 3.5302750806073444, - 5.623701737032925, - -3.048559332327405, - -1.7927761727406366, - 2.2501008966231493, - -0.0434390996019198, - 2.0713629857341833, - 0.6667391023716165, - 7.138508838403462, - 9.117134927041638, - 2.844253892877252, - -3.010065734551748, - 5.3434391962662975, - -0.03387006007417064, - -4.321302231073703, - 6.015578668701478, - 8.694611177352565, - 2.840831058685417, - 3.590468322991271, - 5.925869307767682, - -0.4632539232111991, - 9.852085447425996, - 4.246050458490948, - 0.0795569848871431, - 6.342863222998658, - 1.4051373647168843, - -2.1635570082088544, - 2.2571055692634374, - 3.578015263178784, - 5.92501466937786, - -1.9992269400077587, - 7.613431338304448, - 2.0586657648069444, - 1.7131255525320113, - 2.850162142184762, - 9.387208612221631, - 2.9743469463435983, - 1.1035216432033375, - 1.5082199385262602, - 1.1770277270238634, - 8.727374689487656, - -0.5503031034740972, - 5.996322472782943, - -2.106014886932281, - 2.7145712429255298, - 2.959255404634817, - 3.113836493861464, - 2.769285267659297, - -0.03383966505561062, - 6.981888952467136, - 1.987340238395796, - 2.5935349892602932, - 0.688685934326811, - 0.6023938118323606, - 8.280187749951624, - 8.657520654006337, - -4.614428004690138, - 5.490273423799091, - -0.45654403516637426, - 2.2552766262157378, - 8.950763875630653, - -0.752654576519053, - 6.198515988684498, - 6.375645140382823, - 7.778627264011731, - 0.0679528135196061, - 3.1097816129485856, - 1.9708437429931311, - 1.2519087257185952, - 6.035823894471679, - 2.641606741377335, - 2.3611442950292063, - -1.2138498292937214, - 5.848272228719679, - 0.9787762749408776, - 0.7896001910941994, - -2.9666200974972514, - 1.2153395327671428, - 8.51216629567888, - 0.13161855421830565, - -3.1983695913395485, - 2.4048892802020774, - 3.2731024798000132, - 5.892377898027779, - 0.6485778189416769, - 5.531378659573957, - -1.8313893011262574, - 3.462656522250383, - 3.0240830103191456, - -1.3988666551884819, - 7.196571559897184, - 0.3669345964179366, - -2.8035394109630563, - 4.692363004269288, - -4.476727261762838, - 0.32343844200745103, - -4.182356703599284, - 2.928534228041603, - -2.7685368080690473, - -1.2654701804392694, - -4.052775980189864, - 2.6577769067459074, - -0.9883034373434559, - -0.3934847099090396, - 1.2274252023207477, - 0.1772146684449812, - 1.4914482504911268, - 1.8188586228106742, - 1.5897815313464005, - 1.0307870297513482, - -4.552732358353905, - 5.596899036377971, - 1.1599206410942584, - 3.4385418183942993, - 6.082213341527612, - 0.7341908164143667, - -0.2480626007455346, - -3.1575191950472297, - 2.5389293824676726, - -1.4003061229056613, - 2.6833282298497223, - -0.5467975634173019, - 5.98852696995778, - 0.21292691886096327, - -2.6893512720716815, - -5.117588668343177, - 6.794322180635246, - -4.5742625010613285, - 3.3548586996326435, - 5.0515600035370225, - -2.900449599496725, - 0.10237610962475915, - -5.064851833194207, - 8.531627029244655, - 1.5742438748697312, - 4.082638432652501, - -5.0770992768786645, - 2.119205675069604, - -0.549498327530717, - 3.5730581737051277, - 3.196962670970756, - 7.035845030498391, - 8.548505437332542, - 2.678325032018049, - 2.171957067852686, - 3.4355159234823076, - 5.376546760599714, - -3.487535293579003, - -0.7959857552014767, - 3.109184499044637, - -0.034074417858167665, - -4.463432440942218, - 4.754451040108373, - 5.977086152281335, - 6.3113939537838615, - -1.1073355025666125, - 8.245632488073356, - -5.2333112598995895, - 5.178870586953865, - 0.6180633531176227, - -2.26460261809812, - 4.353674921953694, - 2.8072255410103386, - 1.521416200823173, - 7.589366619945358, - 7.701394142184665, - 1.2116731292036584, - 3.2138291408691844, - 2.8443169344773516, - 0.8903178116947174, - -5.108687151576169, - 7.717847243550239, - 5.103365026900776, - 2.2950781198168375, - 6.397420501802669, - -4.784056687598436, - -5.164879189057719, - 2.612616948933114, - 2.368955342992421, - 6.57506537945875, - 4.983841437905054, - 2.50680520340803, - 0.9418427383823713, - 2.346670739637181, - 6.7670420058449485, - 1.1729036494953344, - 1.3973552011354742, - 1.984364716958311, - 1.1219650572007647, - 1.854444243223755, - 0.15395235570302412, - 6.207396756273517, - 4.902381553967024, - 4.057220866025185, - -0.1327819842430041, - 0.24745711201195134, - 6.1793343047872735, - 1.8642901437174684, - 0.6795484548721835, - 4.802713069866874, - 2.192594562354952, - 7.504825326157448, - 0.4360785367712627, - 3.0969826788534904, - 0.3149099546820246, - 0.631302944620672, - 4.008347085568968, - 5.796200617136318, - 2.690265077072964, - 2.4509671492071647, - 3.1794303634347654, - 5.480282099311519, - 3.793009761585952, - 6.694411441476124, - 0.14085170243202885, - 2.6005776440097637, - -5.2332737609043765, - -2.9808615128824476, - 0.8786289985481496, - 1.8675196537055403, - 1.8798070856567528, - 2.979399276715977, - 7.348120227074838, - 1.0545657973863674, - 0.35836880076700756, - -0.26505513627447935, - 8.37604052125493, - 3.8108946951851164, - 9.371530125128047, - 2.1527731861407666, - 2.22024217006518, - 1.0043860933717168, - -2.8223649837661275, - 1.4529377327135113, - 0.315286921325931, - -3.759919055529933, - 3.192557001334405, - 5.99258651557055, - 2.8135841369438124, - 2.835625816399913, - 4.784946846678241, - -1.7062587841124341, - -1.4443605566411828, - 1.599719712031716, - 4.626872133922204, - -2.066200466458587, - 3.4202402597721107, - -1.9258775472193792, - -0.7109237030323599, - -3.0633148300714814, - 0.7916130122573279, - -2.8003481525863623, - 1.2805196495791191, - 7.641070031410805, - 6.899822557600844, - 1.6947028912538717, - 2.5581600518961483, - 2.0034929243649846, - 5.857911263653215, - 1.4636246547379912, - 2.8971993456484375, - -2.251511707977432, - 5.884447799046445, - 6.7644617214749285, - 2.4674566860698466, - 2.399380076812881, - 8.639067607097326, - 1.4161103959753811, - 2.655889404446979, - 1.8657322395014868, - 8.099395562761458, - 1.2882372797576638, - 5.344775989736017, - 3.2843163197624916, - 1.3268692580615533, - 0.8743822373812074, - 3.4891420513567053, - 0.07385661891207071, - 2.922503933319907, - 8.714379542426268, - 0.6501668013700235, - -1.1375008855416793, - 1.857754709954258, - -2.9945232842258678, - 4.684544304995022, - 0.12886049121117665, - 0.03972938223109909, - 9.237892036506507, - 8.51762483804629, - 3.3724974386724624, - 3.5329200482619085, - 0.8927369288119711, - 1.098034894330614, - 0.0766899373263363, - -1.5153756903132682, - -4.859313173242173, - 2.239424598692307, - 0.3087161707098317, - 1.4471925711686535, - -0.690409487135307, - 1.6160860392915781, - 2.7508251678939137, - 1.688227865698469, - 1.8258302446153771, - 1.2362379094640268, - 2.227100763719389, - 0.013469605778813766, - -0.2565112959825642, - 2.3112040766131825, - 0.6319471784615154, - 0.20327688152306575, - 2.604414592341301, - 5.66856972968723, - 2.7980140743746076, - 8.67085362838519, - 5.918440790189692, - 5.7224556859282, - 0.857285364668508, - 5.544811900362975, - 9.4435138232807, - -0.20236353549092811, - 5.016793650411961, - 2.720699822325314, - 4.5479069977602204, - 2.715983316290806, - 1.7525824693752088, - -5.264974061070002, - -0.6496290315234062, - 2.367614338923079, - 0.6879917909303833, - 1.3029286630363872, - 3.0138918746597065, - 6.640804353774791, - 2.7172754438040307, - 5.76419355748975, - 5.017375178348365, - -0.10816025840842662, - 0.9453881730249583, - 6.720643124414721, - -0.1103631054118109, - 3.3408766939456034, - 5.794047549702596, - -2.025824021148328, - 3.252234698808337, - 5.530672000744878, - 8.64747695134738, - 9.515097696825404, - 3.2344927992474717, - -4.561284055904563, - 5.603927007833755, - 1.6239964904833328, - 1.8190481024621308, - -5.303239347416054, - 3.4400884108742207, - 2.076151202158285, - 2.1590840988805513, - -3.874933358494983, - 8.009236378478496, - 2.742251873418243, - 2.4574402301105303, - 2.1704695708632493, - 0.07441695251940642, - 9.142691879015315, - 0.09950685263139657, - 2.547726388955141, - 2.4264440031043555, - 8.995420023183437, - 5.928160199896791, - 5.10369858225642, - 6.797099162610654, - 9.891558600174584, - 1.6271653661516037, - 0.865228175916761, - 3.293969600310039, - 4.5338781574902605, - 1.8576515517527716, - 2.200264025873621, - 9.229541062816832, - -0.5258640404899334, - 0.7878662950097198, - -4.809662866623755, - 6.172140436212999, - 2.353632835509077, - 0.3245596351457882, - 0.7492161994440059, - 2.6243550810331664, - 3.6033101201399518, - 2.883674831846493, - 4.777864163973319, - 7.608122293011118, - 9.094148010265082, - 2.8586547600235472, - 3.0637538813442333, - -0.16306496309051946, - 5.978283707847633, - 7.0152850555910025, - 2.089439744209332, - 1.2699966622815706, - 7.632606479355867, - 7.426884733347851, - 4.919860769652532, - 3.4636433196516427, - -1.185439361099015, - 1.223042401715309, - -1.7204930505004916, - 1.2498940606612439, - 6.096280333402219, - 0.0255562791229087, - -4.7421129527816, - 6.9134628087321275, - 9.345092400602578, - -0.7428833847718531, - 7.751469449471995, - -3.174355411099064, - -0.4389593568137036, - 0.7889164889254271, - 0.42671004071595564, - 0.4146530713836919, - 2.9852951657239575, - 2.420596392633052, - 7.280976775617019, - -3.9833538656439123, - 1.8123279460938362, - 5.254191706507663, - 2.988686456685128, - -5.122771852329393, - 5.460160945532948, - 5.556392417120963, - 1.1989693659532146, - 1.8856338222888531, - 1.4304240447047571, - 9.103673874712799, - 0.06974033136878711, - -1.8634596072735357, - 9.181488312562077, - 7.782179970735101, - 2.0106552241346183, - 8.423518536106023, - 1.5602445629709538, - 8.192057648102823, - 1.166091512538277, - 2.924903190780516, - 5.805348422221177, - -1.870811325838246, - 5.497133289900674, - 0.6912014452029617, - 2.4494309050757823, - 6.214442790508838, - 5.532218926098756, - 1.8484648675848672, - 0.5357420048696545, - 6.168881879285348, - -4.164441414751242, - 0.8497563909106339, - 6.068046616819917, - 1.6311217190066913, - 4.935653352145963, - 2.909436523764689, - 0.3586354983898887, - 2.6396021300049144, - 3.4768890569507467, - -2.888866342024628, - 6.580642289649002, - 2.302982426221136, - 5.055472805495961, - -0.4836179568565782, - 2.6416319996966986, - 2.3803682290271317, - -4.975249596900043, - -1.4678816639945595, - 6.54720672263416, - -0.943030719721922, - 8.06944049964118, - 9.456410932217949, - 5.477892548341206, - 2.0069868969636064, - 0.33000045858721744, - 0.45137009084748314, - 9.585272571025595, - 2.6585240479374606, - 0.8401318359631659, - 5.921237265866324, - 7.0614974156154044, - 1.3234965998892707, - -0.19082410082550832, - 0.9482892986162604, - 5.1980514735827015, - 1.8648414428434004, - 3.8275970013636003, - 2.145441639200901, - 7.18545866225611, - 3.7681560899027025, - 6.7706972228375815, - 1.710843392703091, - 9.653896454935389, - 8.991595342866164, - 9.186382157891034, - 9.04406304944811, - 0.8172915176930347, - 2.7566256486526353, - 9.660910576572753, - 5.774924628332689, - 1.0341297924498363, - 6.776970079531831, - 6.870337511570097, - 3.316407570037295, - -0.7327186727816404, - 1.4785073400784159, - 3.2646800316507143, - -0.20914306937205182, - 4.64867840898082, - 5.091437827560491, - 2.543828629721811, - 2.491519287769942, - -0.13127409974118892, - -0.6849444346996574, - 5.704748046506554, - -4.580428758802872, - 5.9276986115834305, - 5.949946091737831, - -5.112703533067682, - 6.328840062412349, - 1.3725722459483412, - 1.484950850899703, - 4.922692136902319, - -0.26360087335294413, - 0.3972863993323734, - 6.43499018390537, - 1.9261614464785353, - 9.25217428814158, - 3.4887977439401117, - 7.798413137478559, - -3.859332588932147, - 1.0076305806755113, - -1.595328104377359, - -1.9345755656466876, - 1.3656568430290457, - 2.010239600296628, - 3.0842970345182317, - 1.8307019509259435, - 2.5249665379978907, - 0.21114084691696372, - 3.010763869995198, - 1.5804254258562025, - -4.520042320218686, - -2.128356334095731, - 0.7405047744804988, - 1.7154819971091906, - -0.8522515684542971, - 2.442382303303678, - 0.18784706156999456, - -2.109265073450941, - -0.45500559588426437, - 0.7348284376716618, - 1.7123931297303872, - 5.254688512601999, - 2.7456168285842244, - 0.5416658212070915, - 2.301238469829127, - -3.1464762215917483, - -0.9007639718009747, - 5.42006148595848, - -0.9861660783712057, - -2.162965897976326, - -4.493082242249678, - -3.8189365772831603, - -0.10234080732201847, - 3.8222780518158883, - 6.069040078680538, - -5.257236694544421, - 4.043152750327152, - 2.9400998090483847, - 8.123198210212966, - 1.1001939822886846, - 1.2565680855375772, - 2.245798308281623, - 2.4479921134731173, - -3.158270658414151, - -1.5481370872038624, - 6.312918687487506, - -0.37121749047904795, - 1.6919954011846836, - 0.6875554834459174, - 7.242510466143665, - 3.2722108293917302, - 5.8160212902859705, - 0.26737489698121397, - 3.0063850526444735, - 3.506124855697979, - 7.042641095704005, - 3.3569127880879672, - 1.5852174746984395, - 3.6751882693142797, - -4.165220031935649, - 1.215199283565774, - 7.90308322296078, - 1.5939925329095328, - -4.664195921536808, - 2.4132307103650708, - 1.6273049780055568, - 8.030453359488645, - 5.926901407210981, - 5.96945226815641, - 3.0528213692017427, - 0.5294928795205264, - 6.111198931739082, - 3.27826803975091, - 7.979729831606848, - 6.579075127990691, - 1.0644579389040314, - 3.102471494981852, - 1.6526255527926923, - 1.7127900541239869, - 8.283760640459029, - 2.1924222459051204, - 1.900806515428295, - 5.329619827785321, - -2.071511831927549, - 2.1229332814500315, - -2.4852779587449625, - 3.4704642694533496, - -0.37053887420146553, - 8.385984728405884, - 4.493223761008627, - 2.180319410350078, - -3.01208855357939, - 1.332983186514152, - 6.130263721597461, - 6.9534807344215785, - 5.88853010829384, - -2.8407853967671577, - 1.8033610815004772, - 5.949222221028675, - 1.9889057182006664, - 5.176870999104773, - 0.9709025783457912, - 0.4775110339612653, - 6.003172783895949, - 1.1595497820232883, - 6.039896301978691, - 8.88875053895144, - 5.660666726152205, - -0.20707853144034163, - 0.4656841519810458, - -0.46729412109856766, - -4.763487218056729, - 1.0575797208447806, - 1.4690708457781543, - 8.201368891883424, - 6.322509791870492, - 1.3428277584119488, - 2.6268228995812533, - -2.021077629389779, - 9.536296205942017, - 0.05281985636909039, - 5.667685369387791, - 6.0217023360515896, - 5.878501643642019, - 0.02298604850952251, - 5.729457157547902, - -2.2733129918903487, - 7.357345572460884, - -1.6602227754960404, - 2.8933777470936346, - -5.300255477680182, - 6.674143746202342, - 7.354433017740983, - 8.32057151070352, - 4.986715253364944, - -0.8236511115608395, - 3.000653918731319, - 5.142268479074093, - 4.991873612764421, - -4.462314080258194, - 1.4099959224940581, - 0.5140333598695296, - 0.462038563308794, - -0.5580698037160144, - 2.4156214850354365, - 2.4150056047346644, - -1.4348713625629237, - 9.37189601203025, - 2.2128480268481603, - 5.501830807729627, - 0.5970505131245347, - 1.7086361564802768, - 4.966871116438676, - -5.51059720745767, - 0.40783914628227114, - 5.655657432376619, - 2.1835504862122175, - 8.168986002754655, - -2.7193188251020834, - 9.398775404415085, - 3.2418349793456707, - 0.8676509750580216, - -4.113737353548256, - 1.024007404044521, - -0.34756324082994794, - 1.9602376164792763, - 0.7832705087881328, - 6.335484216782878, - 3.848417262983378, - 2.789319415517467, - 2.7804749683831655, - -4.209835262087807, - 2.134517779191862, - 0.20877152273204996, - -1.6896473650266692, - -1.2400823830799401, - 0.8168266270138272, - 3.003065455584158, - 2.2137576704758306, - 2.3334723718138632, - -0.8022301886454714, - -2.3591277338516994, - 3.269962993932029, - -2.0834230276898755, - 0.9951956155368633, - 0.9691860719679056, - -3.888839739561202, - 2.1629207058674904, - -1.905675289518531, - 2.69453691444355, - 6.701800635735289, - 2.5725594382816372, - 8.588496425207529, - 4.7106805174377735, - 6.410515675188265, - -2.6226997711629716, - 2.072002183326608, - 1.3526862546035745, - 2.1997548005471264, - 2.526355377006503, - 3.3454645401850533, - 1.8236407076363763, - 6.637010415903734, - 0.6187101895208668, - 9.301085778983579, - 7.726784389543951, - 0.9099830270183308, - 6.722528024137925, - 1.256374452711205, - 6.793998223541745, - 3.0663208923461376, - 2.462996441838422, - -1.2483010887074464, - 2.4878297941421663, - 5.988784487203425, - 9.308199852291192, - 5.883351018668258, - 8.143463243475388, - -0.8356458655755094, - 0.5497825145679909, - 3.236547594377735, - 9.029397780799197, - 0.22996970906321432, - -5.012819578978871, - -3.8497149088058915, - 1.7755407000814296, - 8.59826241534019, - -0.4075788598887008, - 0.5821111590672242, - 0.23063765524325244, - 0.9189563098666551, - 7.232389094906414, - -1.268420609294997, - 5.7521552238840465, - 2.203239339828908, - 7.005547360934609, - -1.1313653909462507, - 5.67130135575973, - 9.377013452063188, - 3.4162063856020475, - 6.891357953756193, - 5.572513194602001, - 9.616751460142105, - 7.3777860186219915, - 3.5562906047735603, - -4.282360119923921, - 0.6698010007632262, - -3.2554024637200842, - 0.29250443938453025, - 6.425718881533466, - -3.177602331295984, - -2.454493843289483, - 6.314811684076483, - 8.979560158834992, - 9.870736213896537, - 8.757264493637411, - -0.003453712350984302, - 8.817969535806293, - 5.843733799478246, - 7.054684804368724, - 3.1919023793630075, - 2.699640057234987, - 2.141516681314163, - -3.4472292168477012, - 1.36908126062115, - -1.9441012592167115, - -1.9236197068234189, - 5.397184307275612, - 2.0757701792890675, - 6.778390763843739, - 8.443855120253565, - 7.08532983610067, - 7.9608745265204846, - 7.225488139730609, - 1.845551458086398, - 2.6478648952083716, - 0.699909602488156, - 5.578408909149145, - 2.3707672322763456, - -4.360423816613405, - 6.34034815381996, - 2.5123983953755586, - 6.234127752856539, - -3.403233447929865, - -2.6398216695932124, - 0.11824856949582217, - -0.4560083455354007, - 1.3623351137161217, - 2.488437018998219, - -2.0996984449895026, - 0.4529341843863447, - 5.7316943952319965, - -1.6794395006623484, - -1.662952700628585, - 0.7528252276279854, - 1.86526470435675, - 0.8250661486800847, - 7.545149459365755, - -2.9784914139412986, - 0.7955122992388768, - -1.749696914354937, - 3.007033532357639, - 3.2539694960317154, - 2.325020884091079, - 3.0682380835267087, - 3.4877633370885603, - 4.755907494880818, - 6.128266753985117, - -5.363081889079644, - 1.5887297020473807, - 9.505091939439223, - 4.365143981465876, - 6.7548503826243715, - 2.5052979166231886, - 1.4353576508393462, - -0.9928554982734809, - 2.922494124533855, - 8.10081092078275, - -1.3002214585010545, - 0.8404824712467401, - 5.94837787669559, - -4.767683732401647, - 2.0017751275916296, - 7.915636914038291, - 2.5822586807239722, - 2.8495043174738024, - 0.29281685345900793, - 3.07193328710613, - 0.32780731449595507, - 1.078728624062782, - 9.212142393190357, - -3.234096488944491, - 8.99985503777453, - -2.855040830930229, - -5.295863603354861, - 2.9629710484192806, - 9.59196741817357, - 0.7743349776222785, - 5.792043147303167, - 0.7308440213299643, - 7.350415660821069, - 3.495075238229184, - 8.647182976752868, - -1.534758576855379, - 2.073463430160869, - 1.963332441387051, - -4.694354180861564, - 3.6714354834316927, - -3.9262388559123464, - -5.546500365026073, - 7.445083723470979, - 0.5343682186596866, - 3.183237056362217, - -2.403816101636754, - 2.8857332178958295, - 6.672428835630001, - 3.6953141788532005, - 5.29590329943819, - -1.8554545565340235, - -0.17610077417452594, - 8.271235986900548, - -0.8302414238237459, - 2.4378481735230384, - 9.57202802197544, - 5.557141877865675, - 6.5268978634694035, - 0.8407924426877699, - 7.979052578435055, - 3.117590024813628, - 5.96352037754916, - 2.094825703273501, - 0.07296691179388555, - 1.8079190555258078, - 1.7205218009412788, - 5.730311841139373, - 9.168679321911021, - 6.63794178471708, - -4.770023224802359, - 6.32579824811486, - 8.060919532649441, - -4.3498104635619965, - 6.056146366036844, - 1.3888378059597648, - 1.5681318199046925, - 6.934114111947524, - 4.553233986454347, - 1.4275240710301833, - 3.747256941001211, - -0.7793987571499036, - 2.4159574731318942, - 6.360954669715619, - 0.4084551726607402, - 1.7502096715103717, - 8.32356944907215, - 9.411852540453843, - -0.24749985885791767, - 3.6441437548002984, - 0.6638796329985154, - 0.49554468852439093, - -5.288299956200278, - 1.5867630719594317, - 5.266978763389619, - -0.1730881110987882, - 2.027850474654688, - 6.70043355578779, - 0.20699152625797068, - -1.4169490537802918, - 3.567763215349293, - 0.2333312464661514, - -1.4878662123333741, - 1.091060642589443, - 2.4017502719866424, - 7.9782861690822, - 3.44782406334824, - 1.0432269698264383, - 4.640994658240865, - 5.749646077991115, - 6.089790596813214, - 2.9853600065784107, - 1.585551391839002, - 4.403944696472623, - 0.29951265146255124, - 0.24389931462395698, - 0.8540781982541754, - 4.611025267027386, - -0.45181284082359413, - -3.5542731441518876, - 0.20103598685438334, - 2.3975234423332497, - 8.6230597387424, - 8.663118774999928, - -4.529682685118797, - -0.8760724945413672, - 0.25604543050627254, - 9.032110091018815, - 0.19628068798147708, - 5.911953902186222, - 8.11065712561067, - 1.5106611736082836, - 6.483990941242417, - 0.9154031653035811, - 0.4733209855793123, - 1.2729172153754813, - 6.226232576039953, - -3.7857216516839913, - 2.85210708040812, - 2.3947148486545013, - 7.649662954804599, - 9.16162216363764, - 2.2116236694661873, - -4.445492844370273, - 0.11508527097851792, - 9.076362458267964, - 0.4348146585260673, - 3.688186838147284, - -5.321770884683309, - 7.415460097453132, - -1.9534807833504129, - 8.50852643998329, - 0.8570152188041182, - 3.002819999704473, - 6.0288006491872315, - -3.2528245994908955, - 1.425515401254983, - 2.518619468789845, - 2.6021768268562155, - 2.414457971274285, - 8.811798173197223, - 8.463135654386775, - -2.3599709268161466, - -4.470741594770652, - 1.9029054733785435, - 3.5107539529337575, - 2.517914528908818, - 3.2373739399765995, - 0.9559242825654067, - -1.4022193331720425, - -4.164011090781615, - 3.5098720942728066, - -1.5152128618720702, - 1.2042015283823664, - -2.5223273022794563, - 4.6568722554070785, - 8.748779660690749, - 1.64867887605269, - -1.6451264272207415, - 2.223501415745643, - 8.983241413406752, - 0.7856413355998099, - 8.271058597380113, - 8.759786053557635, - 5.964851993500417, - -1.9854392851535787, - 5.417165541146182, - -3.6442197852501232, - 3.4828188869815073, - 8.467767959705135, - 1.2727275656548527, - 8.52188240945984, - 1.2193859287039661, - 1.6753573505177883, - 2.7578999432181828, - 5.752416727518017, - 3.4895594687669718, - 2.848717380504166, - 1.1007765674235717, - 7.3936145172341945, - 8.335571225152114, - 1.3472097319919996, - 3.1371705224091144, - 0.4215143657193758, - -2.0292815257034817, - -5.49035861680535, - -5.183291470456518, - 1.8343121382967842, - -0.30212063468598305, - 2.67347488141855, - 1.2506741064376266, - 6.705326698795701, - 2.3117777668167516, - -2.166111449868967, - 3.3066654185985973, - 0.8743752567181792, - 9.433552236501237, - 1.3666782032393632, - 1.130142268909575, - 3.2738566103698905, - 6.5968220577140055, - -1.3891345838746347, - -3.5128981904432948, - 5.0804414422022335, - -1.3058470702411964, - 7.130933426715227, - 2.4273980019954204, - -2.1608284982186197, - -0.9100596860292837, - 3.5894835328702106, - -4.751280916256097, - 2.569585024243075, - 0.2919735183319088, - -4.406471808552807, - 9.003775888319385, - 2.7525231897174263, - 8.491374502683652, - 4.376946832713647, - 8.527523053929686, - 5.632602084917159, - 1.4052219593748756, - 5.5737253668239655, - 3.4569678545306575, - 2.8171500161674357, - -1.432944115552822, - 5.697969375029198, - -4.621445460935588, - 2.0787510016080533, - -5.326683128959758, - 0.18067104116133456, - -2.502498411746137, - 5.629349911367992, - -1.6890235276676102, - 3.045990978436232, - 2.068467399984089, - 5.084093781542543, - -0.3929337578092091, - 2.5605365794849444, - 5.53869708350438, - 2.614522456632436, - -1.5480239773209241, - 3.5678945576150123, - 8.83401771512541, - -1.5963844207514608, - 7.624379929762122, - 0.5005540393521262, - -5.527784938566744, - 2.65125893195905, - 2.130758952863588, - -1.8332809453947294, - 9.30394757121743, - -1.446331856826678, - 3.2165312128841435, - 4.04687189616058, - -3.5056213436587336, - 6.666219551384144, - 1.3673469667147284, - 1.6231652648575179, - 4.4948549236610305, - 2.0815856253285214, - -0.60043979994161, - 3.590976451375838, - -0.7453152161686788, - 1.564348734142829, - 5.541589960918232, - 8.202930465965972, - 0.7444615247059749, - 9.587703248667736, - 0.4935395980500209, - 2.02135191370068, - -2.63757568386335, - 1.6931078983944303, - 6.194891401826324, - -4.755698900045702, - 3.053941263428849, - 1.738035826808363, - 5.482444085458718, - 8.578249176772534, - 6.622930301440895, - 2.125057661575636, - 0.9054222604976315, - -1.7109375809695786, - 1.4198761476337516, - 1.054867119727166, - -3.925252521521188, - -3.0436012570906885, - 2.4145304719634875, - -2.7089004374087096, - -2.5781187088980415, - 4.040219917034839, - 5.7177319240579125, - 0.41648218881027665, - 0.5737150782632761, - 1.3605157350455324, - 7.762686896051611, - -1.890859886923358, - 2.9869526962840838, - -0.8018564162424652, - 2.1407876001056168, - 5.863579989317062, - 1.1422827886056979, - -5.034414504153599, - 5.306443885502887, - 7.855634915825041, - -1.840671726488353, - 3.1453425959097934, - 9.521053083576877, - 1.1797955103350146, - 8.34289646049561, - 0.9864026286857854, - 1.5511568318528561, - 8.434271139212683, - 0.20427819364048902, - 2.0271112325590077, - -3.9356698611216534, - 5.870340206181536, - 0.05269352565779371, - 1.7920616044663369, - -2.42138548840195, - 3.475007131820548, - 7.011108331408282, - 9.515231228026291, - 6.346792668752203, - 6.494414623263908, - 4.472927613760124, - 4.524003924372726, - -1.4134186597873823, - 8.723691479901538, - 1.8639456444607319, - 0.7382556576116613, - 1.7673853588875232, - 6.396387432623712, - 5.591000021046794, - -2.2765896318071217, - 6.2962062739823965, - 2.4212794737100123, - 2.697188160050856, - 3.5064505365695777, - -0.9661428559971644, - 1.1653071361402214, - 8.832158933958235, - 1.926594996120538, - 2.2382815782643033, - -2.138572477012913, - 9.020160211222818, - 0.34070599225005027, - 3.3797625149541055, - 0.05703965444493409, - 2.305032462030537, - 6.2463349336626495, - -0.6584707349200902, - -0.38389619151492244, - 6.120169056030916, - 1.6388345686915071, - 2.205438800430803, - 9.043723892497786, - -0.05324007737301528, - 0.3651143038587914, - 7.001822659426594, - 2.5765444604895604, - -0.04862648951907117, - -0.8854025072266365, - -0.32410129627632506, - 3.0812142492739736, - 6.295356520537049, - 6.177967110174736, - 7.079564521405287, - 1.83353114343839, - 3.2388910348859192, - 8.913712343332712, - 2.4375146713115385, - 1.2634733710281858, - -4.414938136285208, - 3.4759377909794242, - 6.569247134786052, - 3.3257450358478975, - 1.0495790550303425, - 2.9650735879571166, - 3.4456722296078293, - -1.9425450759671543, - 1.599117095043776, - 8.497017451637193, - 2.6579556546365266, - 7.910087173332323, - 2.8799774369661812, - -0.07025037126624543, - 8.073942200277664, - 2.3342142619361534, - 2.8830916269966758, - 9.100411166653252, - 1.2058185139176982, - 2.675872700135464, - 0.9666762827582379, - 5.616586906563049, - 6.905637710372154, - -4.860074337814643, - 4.0158954528166, - 1.0941869678450136, - 1.3322841635744591, - -4.8525029564210955, - 1.6950143873386676, - 2.275866960775223, - 3.7546696075480233, - 8.522580158693797, - 8.479289443791219, - 9.084376204745716, - 0.524887035594922, - 1.7930496347425775, - 8.36265519445222, - 9.13207967711533, - 8.728248933808025, - 5.104280192568869, - 6.932520932186675, - 6.57954219836973, - 8.358960821108504, - 2.5870592720871555, - -1.8119057173172903, - 1.7265071935675682, - 5.343747915510189, - -2.5904371427923047, - -5.105623763927343, - 1.7555879054859012, - 7.85831749823218, - 0.3955986367670087, - 2.693545835650025, - 2.2783352602443867, - -4.107147221405172, - -0.3589112571594508, - 0.2739780970973445, - 6.00113681801525, - -0.9520046557887152, - 4.455509206119695, - -0.07994742403490834, - 6.912346070734264, - 1.7374666740318419, - -1.9482137044069845, - 5.243596178912719, - 3.718827522220301, - 1.1880164187237157, - 8.047695963346682, - 8.117318312531806, - -1.5085045180979209, - 8.80835524866147, - 2.9999212372772712, - 5.458046876567976, - 0.007803281932174618, - 1.3849554785538867, - 8.51477432156869, - 4.656161890950504, - -0.49453412636627153, - -4.9425646575433895, - 1.5754507134189302, - 4.071093984813563, - 1.4821345261234662, - 2.815670718021292, - 1.9423374489222467, - 5.64234093990883, - 1.711516119661729, - 2.5246316441116576, - 5.404768257953342, - -4.933144619659127, - -4.0862479358951616, - 2.414531419272294, - 9.27182973316845, - 2.2064135982664714, - 5.872298049989269, - 1.4429082064623937, - 3.99304417572891, - -1.7976779555774933, - 2.8060601507477996, - 9.544330963742757, - -0.2234861369430893, - 1.1926141918363296, - 2.8595940374636495, - 2.6911712476226657, - 2.458521202978513, - -2.694375476554727, - 3.9776603483448296, - 0.6718385790624146, - 2.37716045025641, - 4.041421509916807, - -1.6349543418763945, - 7.9212454675679185, - 0.7721147216829433, - 8.959113895222348, - 4.982386370940765, - 7.1514158587805365, - 4.073127252924829, - 3.973102469449036, - -1.4206098126378905, - -2.884552512926147, - 1.9047385965830614, - -3.169287508333552, - -1.7392144968569563, - 0.7721044520820948, - 1.927206272793925, - 7.104641765501545, - 3.4505110590561854, - 0.8733130174974519, - 9.266268836620407, - 0.08700274201436375, - 6.052240993895984, - 0.9007896354342442, - 6.173886287536836, - 5.907638810176699, - 1.9606259324926214, - -5.130693452152175, - 3.0132523997110416, - 2.4628682686429966, - 3.3604641188713784, - 5.456330102509671, - 3.1129611127328216, - 4.621919115236012, - 1.6051966558753044, - -2.395592286301594, - 9.415942637822253, - 4.5551016138441645, - 5.462041681472252, - 1.2553444252956512, - 9.125289294805025, - -5.19635425788795, - 0.6479316122636503, - 9.211129276541376, - 4.088576979982686, - 1.778078098119498, - 8.272830237615167, - 5.941247087817222, - 6.483218672754511, - 7.836505848839812, - 9.10777300419422, - 0.8697894759196668, - -1.8048153062968533, - 2.6932056631239343, - 6.270438904360643, - 3.793841292975147, - 5.93176798393608, - 0.5794319523472153, - -1.0634626786112789, - 1.5525130634435254, - 1.9069750675731074, - 5.450872922288456, - 3.352999491608821, - 2.6061036797014023, - 0.46996693176866594, - 3.089799989155103, - 2.1768196533032103, - 7.209632078897733, - 2.9382709469704604, - 5.81830042125279, - 3.0254259849920686, - 7.952336979799083, - 6.556182022826983, - -0.1976664554077333, - 5.064374587699065, - 2.5790684611219734, - 5.416054005071723, - 7.929922860554962, - -4.987485362225389, - -2.365232243588474, - 6.067477778583785, - 2.7165906101272084, - -5.0554658081074315, - 4.826017906934126, - 2.3051068664341603, - 3.2425676342002556, - 1.2996408495052318, - 0.703193985050713, - 2.7805627349610846, - 1.0491896153647293, - 6.821299225780244, - 0.7046460079936201, - -2.953473023647294, - -3.6590226625841997, - 0.4254855627307656, - 4.5834436824020655, - -0.1264574637622443, - 0.062170134272150034, - 1.0044135902927296, - 5.894066030179587, - -5.032302428711589, - 4.3565237912861, - 0.8204878684140501, - 8.542998995034315, - 0.19522163995677777, - -5.105510462957291, - 3.664400379320447, - 9.523795502928193, - 3.1412037401144466, - 2.2838679019892427, - 8.175845575985958, - 1.4812611753280103, - 9.229352687073469, - 7.315547660481734, - 5.826430520451797, - 0.7545773335194408, - -2.2423574079782207, - 6.472756705414401, - 1.37941517062476, - -2.1564940827513968, - 3.372013235866089, - 2.3650725020331045, - 6.568125635833751, - 2.445340791793013, - -0.9932390025071863, - 6.221281466545461, - 7.995363198747193, - 3.5240304820715087, - 3.7052514666884435, - 3.039674786023824, - 8.72316174744997, - 9.686001035805639, - 8.472376648409222, - 0.3369873707042546, - 0.4055299277861853, - 9.055907499616207, - -5.005667267446557, - 7.961191247169811, - 3.229307450854857, - 5.780672932325554, - 6.190242116673266, - 6.102394102049797, - 4.171372057552599, - 1.241947275086106, - -2.0859279953693677, - 9.473391633273852, - 5.49488016127507, - 9.122434389343034, - 1.0929961023746564, - 6.043910303777906, - 5.392428857667593, - 7.4885983371889955, - 8.349677984222893, - 9.566987967368911, + 2.26612718696679, 7.877304234882818, -0.2448122627872643, 4.516540904583949, + -4.185123130466475, -0.3563651520223698, -0.8099006227273609, + -0.7273773022983425, -1.0774494744803462, 3.3295276863355623, + 8.016118846675909, 1.566371903855566, 2.527331443604742, 6.0204023210462285, + -1.2725524662708634, 1.6069492541685462, 5.49339016416923, + -0.14877824811217932, 7.541563678570806, 7.828715198686858, + 8.78143506494612, 3.0724004942655743, 6.910282329799579, 8.520562682219973, + 3.034769667067511, 1.9556477732053121, 1.391521150600587, + 3.4951871559764998, -0.17956672474858976, 2.26349058202461, + -0.5435329290392841, 8.741637845270487, 6.471130230045931, + 0.4137720216823771, 5.314452356601059, 2.6065034944063608, + 6.069220385698501, 3.3364078398310455, 3.328331508170648, + -3.3524926199567573, -1.435579284246872, -0.9751170795016273, + 2.0364383183517596, 1.960212653802774, 0.7864521202540135, + 0.5657911702861587, 3.092853905227683, 5.01806876941713, 3.8663921379199855, + 2.821039512684959, 4.622541969701707, 2.9858484817831323, + 3.6261134085537847, 1.1724037712799356, 1.3838290511047608, + 8.806048701083698, 5.668478923267121, 0.8018037690672242, 5.142631152815043, + 5.162406058696506, 2.6062536456732297, 3.2943461105091645, + -4.990164104959657, 3.806517214224376, 1.8949308089289694, + 3.6353370033600987, -0.27148904339677543, 2.7380806442893926, + 3.006631409999392, 2.0071121263434377, 0.04628078340754096, + -5.1377197960285175, 1.0483368306122867, -4.784796367966544, + 1.5862439101500176, 8.756330051078708, 1.5805286130098075, + 1.7098684717663246, 3.200383653069714, 6.709460319064008, 6.307911810299551, + -1.739665781844903, 4.245169768183147, 1.666455373730062, 6.837709319524681, + 8.3481618163966, 2.9875858571030065, 2.8139839176386436, 9.099261178847472, + 8.948801052040421, 2.006202530800494, 6.73880301635272, 8.17611168200775, + 8.773745685376184, 5.91600439185124, 6.104433949863836, 3.7052400992485914, + 6.192779846035659, 6.600091346107618, 5.923022741981018, -5.250204433842824, + 5.223817204947422, 0.696206808198047, -2.9769151747495926, + -4.130522494380668, 7.584957421710554, -1.5598149353078123, + 7.718639481716779, 3.0013319833107084, 5.928077111182149, 5.152861273092454, + 0.9286834020630569, 1.15570293124766, -0.11413301755132071, + 5.3564497446505275, 3.8928146168617306, 2.967358817084032, + 9.258863388399549, 3.629272759041251, 1.6426518374793857, + -2.8569863552591284, 6.781260075162287, 7.624208895126389, + -2.251232030343179, 0.46027511263626997, 2.1982523757635377, + 4.5679304243381935, 7.908571146138121, -4.853529006657921, + 1.5476649669885307, 0.8422206760808629, 3.314306441122399, + 1.435163153918387, -1.729483134322791, 9.254698656553444, 4.161313073939071, + -0.19285497459513173, 1.471278108190918, 0.1733342761260208, + 9.03087243734635, 3.4629830189459407, -2.6264808461106277, + -4.71657716085353, 7.869469706260304, -2.620405496749864, + -1.578270511956123, 8.357815415289556, 2.752648283396273, 5.565302741704507, + -4.805089857063229, -2.1885042710137363, 2.0585183776678355, + 1.1610136154324948, 1.4912027874169376, 5.914379471375557, + 1.3499504765324346, 2.044807431029458, -5.406212771764639, + -2.521892586706258, 6.1418606819986445, 8.415457501107205, + 5.604133372216368, 9.143496250718814, 7.319575349089649, -2.06421150615848, + 8.215989933714578, 1.6857886508980149, -1.0878353251562816, + -1.5829661285262637, 1.4674923894311405, 2.7741856684983164, + 0.9185064155989479, 1.2781037230916843, 6.884473682406043, + 0.2934983262573301, 5.785360809322976, 2.453893016522862, + -0.7453305767736639, 8.396234722381891, 9.850354025725204, + 2.216365887386976, 8.431236102153253, 3.3932288637112924, + 3.6608661914291054, 6.6026731099986815, -4.953410384187296, + -4.4383215629895725, 0.07462075161455901, 5.919009879800911, + 2.95366980628499, 9.444938044811291, 0.9076977968117299, 8.586093101374825, + -2.947154691692993, -4.633162015997375, -1.6398464357794498, + -1.2357874214259623, -5.298383006143634, -0.43896349898626935, + -2.3401534496139194, 5.210537676425541, -2.299537704354067, + -1.1292417029652433, 1.5799175742083458, -0.336520751004366, + 4.223746594866309, 2.8317988965614815, 1.8947275849516294, + -1.67358278514923, -5.253236405380462, 2.219133984219187, + -2.1880534239704144, -1.3375574851781555, -1.6072610776058833, + 1.5397232688385492, 7.036819843042076, 6.692937873958802, 1.082746220482573, + 7.797508199429759, 1.2007123936245745, 1.8770497605398146, + 6.8994754889657735, 0.3012191088043153, 1.068935678724868, + 3.8501454879447587, 1.7790542501409592, 1.9614894543599724, + -2.3388476137009833, 3.110452608712005, 2.488897512781782, + 0.29446492568337673, 9.228134471260587, 3.063679541623608, + 3.127534142642514, 7.2918077503859715, 2.1074622260198823, + 0.03666378061265447, 2.348354665889141, -2.776578577073148, + 2.5981465208878927, 1.9166047514477609, 9.467577997348005, + 5.157166112164271, 2.7420707192882334, 0.589056280377641, 6.296664749024959, + 0.9971281607317918, 5.968437263241744, 1.0571690485567766, + 8.746282612307349, 0.34173616693893566, 5.460155699051275, + -0.33199671017021387, 8.506589166854504, 4.760513163928613, + 3.9122175258157936, 1.819189742944049, 9.482487935152745, 7.768142046743971, + 2.778312560578788, 0.8924815069256471, 0.5781476976836171, + 0.879392015766445, -1.2513183283229647, 2.9135625658416435, + -5.218754075977553, 5.869987475209426, 6.215557257640273, + 3.7965216268335875, -3.978376269047853, 0.6441282455417816, + 3.195727870886227, 7.56439441284703, 3.385762283468298, + -0.24603155345912425, 7.62699568971826, 3.095762191436015, + 5.973306919254448, 2.2140268056041097, 1.1127192954394922, 9.6943693980643, + 7.492005482707253, -3.6717161892789565, 6.318002419686285, + 0.07016674311514137, 1.6940972871714632, -0.08558940895614194, + -3.8815121919455793, 9.249512566645945, 4.598958709603496, + 6.177639401450066, 2.158306022736798, 1.6740916570728577, + 3.2165428053675784, 2.139437242413739, 8.527661461666613, + -3.1283742405260058, 3.0533838621473004, 2.8169855715416996, + -5.02273058607592, -5.114225383806405, 2.7643256614152265, + 5.972647138843313, 8.896241804531897, 0.8767719229947301, + 0.5510963795699688, 2.0798971261268364, -0.20474346020074016, + -2.6385424632674277, 3.0197194877796796, -1.6532785804244121, + 7.350061942234777, 8.424823833262176, 8.59104964106905, + -0.11483904098985327, 1.3641616272742318, 0.9584917078748736, + 9.580245305611498, 0.7483599943956905, 4.655927249095971, 0.900799899593537, + 6.2130604458748, 4.445533750316594, -3.932854365326212, 5.551721373679071, + 8.407643877761046, 5.885232771171051, 2.4313967402599874, 3.669780715212272, + -4.904065807718558, 1.0158008170609327, -1.6272293048652275, + 2.845528271618909, 2.807947902007598, -2.1459588093206796, + 5.608674291803838, -4.561053175109312, 7.69017878292755, 4.905071561851479, + 1.3413222347068192, -1.1824406687276312, 6.738801169688746, + 0.9426274806618206, 0.6751144483531506, 2.5848520669007238, + 2.1630373426657936, -2.7076800307547133, 1.864371841092596, + -1.9682191074896516, 3.4172413227955696, 0.020744702897102174, + 9.769505400367716, 5.798720665320329, 0.10253613057523274, + 6.0749341819718214, 5.357902585098012, 2.4046800092407876, + 3.512704197882585, 1.29949383757325, -2.356963075208514, 3.1765333049669566, + 7.959069530307456, -1.966846171005304, -4.25330821080038, + -4.9219589292228685, -2.197056092175947, 7.616489594588331, + 6.040817035671559, 1.8018917838550688, 3.5407913971559943, + 5.7890179781018425, 3.5262942067172984, 1.9950824464659818, + -1.2893474491122634, -4.63882900188689, 2.6694949944379345, + 9.674111224668177, 8.667295005270228, 5.737081498597616, 0.4107629657054798, + 3.877046863822763, 6.0243859744065915, 1.8838291584410343, + 2.2562445930114294, 5.4540041564283, 8.274269306597581, 1.2052437166236634, + 6.009785777223097, -4.383503344244362, 8.656175590418812, + 0.3181436886883143, 3.1680255522231233, 0.6533605734315873, + -2.0973750071005584, 1.994294615835681, 3.2127097033396788, + 3.439095899977053, 7.2040540626614, 6.785366464604335, 1.9671587153234735, + -1.5827704027494358, 0.2878181187329489, 8.701213078576167, + 5.775702232264342, 3.796888482981822, -2.2656130867226323, + 3.3040363272429416, 7.8336984140783645, 9.341343078834914, + 0.8594581274173383, 5.3238697665732495, 7.72383488521013, + 2.0805761896462105, 5.00590427740257, 2.4523488846181003, 1.530253353729973, + 2.2370825976050397, 1.660862575032461, -2.2119403145718572, + 8.457984430510653, -4.738004795759159, 0.4176833442710331, + 8.521874684509584, -1.6000253603261758, 6.170469016612993, + 5.183781673399163, 9.17207654732024, 8.7802004157023, 3.315232146309697, + 1.7255707001482075, 5.615285248049787, 6.452463946699582, + -4.925951924112487, 2.882800800278358, 3.93467062640467, 1.8659188085616192, + 0.3306654617084946, 5.88741276107328, 2.550510994085204, 1.3678259326902338, + 8.663112992818656, 7.745060334809355, 0.2809562613068918, 5.757109520649999, + -1.762138015439035, 2.8786271321357484, 1.5474645624637917, + -2.261619052143985, 0.46857555701517345, 2.5125424778036147, + 2.672966408932212, 1.816597263740069, 2.340187280432554, 3.634287582524317, + 7.989955726847132, -4.1380036275031475, 2.657718947754817, + 0.013787158369857909, 3.3229210110695737, -4.201062825692139, + 0.6624903490617761, 0.6944889704349064, 2.3533513425377217, + 3.7656997519365882, 1.788749981152106, 0.7204561771404412, + 0.5730477522205016, 5.847178671138482, 2.8793680686193746, + 0.7398060516511077, 3.4301937342836974, 2.531013519887129, + 4.755796561060134, 0.03385492782234758, 2.0252506551361464, + 1.6234611019159673, 1.228843641458273, -2.1668553315537094, + 7.900290985046659, 2.7050616439468067, 3.0006973624200683, + -2.1759904645467083, 1.5375916476358278, -0.2253952541126304, + 3.343969551234012, 2.8107101876639935, 1.0346932550959453, + -3.6532774566258266, 8.814079961490908, -5.097909229812539, + 1.2520930353511095, -1.2672246839647656, 2.293286603007841, + 0.2410596637437222, 2.4817504139530056, 2.248527285829585, + -5.447774337207916, 2.5923894677692516, -1.6454701766763544, + -2.430822876606998, 1.457649746056256, 0.7661499751857752, + 6.0009153574611185, 0.1712479024293902, 9.530954997711033, + 4.983304885063888, -1.8163769564966774, 4.880132622934018, 8.63294213048147, + -1.7947779683144798, 3.8634935719553365, -0.8598586499831854, + 1.7046802605527513, 8.229281772842395, 5.5246578628586045, + 5.398118716576608, 1.5665377764811041, 0.4245517342194059, + 0.42220229215306493, -4.167833021757446, 8.930094781851475, + -0.35446000339359723, 2.0690947296225084, 2.2632723564752517, + 2.278629737720776, 8.756058383175949, -2.384089444260743, + -1.438680090544982, 4.019783025134954, 2.770246387450514, + 1.8829131809196227, -4.477963763370143, 0.32452313825904894, + -0.21195692236210456, -2.161747413311612, -0.1104742560807789, + 2.731352200053975, 0.13773536558903318, 1.7722498157924262, + -0.19267629049184617, 5.9428729939902, 3.1430293610074944, + 3.722242795519652, -2.1106747591923156, 1.0177343680607016, + 2.3476469900890904, 1.3611397625517598, 0.5769222962931847, + 6.296183309833097, 1.1314346686866923, 6.996354905775925, + -0.49731034627470605, 1.6514206933772515, 6.520507562296869, + -2.4876418860943246, 2.2307122674056097, 1.2381767470195828, + -2.41036271414792, 2.8954645460727777, -3.2678317085548385, + 1.0575729842665866, 8.232678699212576, 2.4739770514016617, + 6.4903251593467965, 0.9560520936909322, 2.1733654915775573, + 1.7088617486581057, 0.768606455869161, -0.18151377978512884, + 9.302470491788773, 2.9242421348918497, -0.21070765493454563, + 8.523457662651651, 1.678976168232762, 0.4907273484125949, 5.294112902913152, + 0.9570337069921794, 6.309717848572128, 5.853969411321018, + -1.3623712064374873, 5.889476548951992, 5.9315557030842285, + 0.9762018475430272, 6.3787887818601385, 3.702617423313039, + -0.4259287963564401, 3.3940136837773305, 6.33254888740099, 7.22386178996473, + 9.48026934550518, 7.942085137181178, 6.426147842502401, 6.193095220350733, + 4.7154873457616215, -4.929461685703354, 0.40851879820326237, + 1.0355585657555777, 9.311049935380138, 1.9601546187502212, + 0.8503197268897879, 6.417658240356214, 5.596080884732174, + 0.10266942032352865, 1.979006093526083, 2.0923008866853228, + 4.450351856234537, 1.9178224408715299, 6.065730723024631, + -2.1405682647230044, 3.556202577526532, 2.1423103843101505, + 2.5180534174094977, 2.221808263874568, 1.3245232660550748, + 2.846493012934731, 0.8640007518413745, 5.815377980880926, + 6.8076746368586845, 3.212876640337127, 0.6620465641915558, + 2.8358557130032866, 5.905823174293553, 3.0122412380018124, + 0.6042312258565233, 2.7189140793266566, -1.6466964841111296, + -1.433601831253046, 1.7738882086077163, 8.874211341294819, + 0.6374919565889643, -2.250631300713733, 8.398314862302222, + 3.109991448596508, -0.10447829604288518, 4.7465579152728905, + 2.450563286997713, -5.3495016911775926, 8.243966840080844, + 9.353859126160001, 8.779407481837953, 9.625349294803156, + -1.1690780188806251, 6.883270495069991, 3.420071073653294, + -2.7124407552557543, 2.431871694876404, 8.169142653739367, + 0.10312628339127165, 3.1747240309485587, 7.605851681417775, + 6.778454276450802, -0.33823536051106673, 9.159816946971777, + 3.009476478092635, 2.2639212699097904, 1.9662337900276088, + 5.456163902180738, 6.2728300525670555, 6.046612146481042, + 5.6254154012391755, 1.7448738576169487, 8.702308099646093, + 2.934366073684294, 7.210872628959229, 5.892411059521462, 5.08227461046624, + -1.7395127801589216, 0.1317231915653626, 1.3125074882009866, + 3.0260692912174343, 0.9616394687550338, 1.0133611506450468, + 4.889654943041665, -0.9629338146674636, -2.4724254857034027, + -5.456164226742061, -1.0820298779937545, 1.5859048729025889, + -2.803255229805306, 8.563567374075099, 8.004869380926394, 7.789872652488633, + -5.178475355138235, 9.00872844603491, 4.1139580524028085, + 0.8012152195681193, 2.9547142410904255, 9.368726650392437, + 2.573308753297779, 0.8721362717477031, -4.518618928892753, + 3.038737898072484, 3.494236477379651, 1.7802679565870878, + 1.8305970064035781, -4.721803051184619, 5.4894357947523185, + 9.024945875104052, 0.33248042116655596, 8.978545880756572, + 0.8265498387088497, 5.253669495716501, 7.7831176744839246, + 0.13285521333224828, 1.962292141861213, 6.457116157100644, + 5.325750037176592, 5.080589681950436, 0.9492611156552451, 8.370070015424393, + 3.7195662602507493, 2.306501093822457, -1.943000191988212, + 8.935275055211779, 0.4523697013583989, -3.776936478186719, + 8.525555483994319, -4.612421394543514, 1.382647763042897, + 1.1862068046882155, 3.502817236032331, 1.3690705190155288, + 5.794610055631808, -0.9857006762062972, 5.062053934761011, + 1.6804265993382794, 0.46795210451425295, 5.91865159008816, + -3.274753687313677, 7.117602921781142, 1.1929818334326139, + 0.7770110791675934, 5.987436755285214, 0.6581091618990716, + 0.22582897088511306, -4.02472552189992, -3.281325205464603, + -0.6180917569514581, 6.92089529271475, 4.147765423783696, 3.889305189579335, + 0.3056958065777463, 3.4624723766970944, -0.310507442372391, + 0.8709343758066993, 5.575731062495118, -3.9981833864785656, + -0.021001128775697733, 6.105224149146419, 3.198468413659969, + 5.394911906600809, 2.5417900288708477, -0.8225464773786691, + 1.9292366115723005, 2.580419662349196, 1.4624693592572309, + 0.5847068525339708, 1.292978687785169, 2.5908710486444897, + 3.348522105080629, 5.70882232007594, 2.526697142258413, 2.8387534278746305, + 8.926971356284202, 8.826907454040457, 8.732591313237428, 5.670388913071506, + 1.181592394821869, 1.2455224165480927, 2.612553991589734, + 0.49924191048675853, 3.0163431566816477, 1.2389425711694886, + -3.454256812240126, 2.541300376969366, 1.1855211805598396, + 3.919987236532716, 3.108104199692774, 6.761561693459247, 1.6617163362455774, + 7.988216917362715, -3.7069269200955604, 1.8956754945791268, + 6.513191358838873, 3.0160456028606513, 2.556900557970246, 5.794776377613141, + 2.8913461749272518, 0.5584477187851367, 5.823652757914274, + 6.652661373779732, 2.895484766286893, 0.004865004026195168, + 3.7362302042851407, 5.1590787450811115, -3.2477231320830846, + 5.160237785597462, -0.0019050703376409799, 4.6657067577511215, + 2.533925071913782, 7.49038147862633, 9.234610799969083, 2.8091581370951944, + -3.0852521411396947, 3.8404146939567805, -1.7364762360283625, + -0.06075348821321888, 7.855533253661598, -4.606191298490445, + 8.930715901769902, 6.433824620680145, 5.023330657133031, 7.176348684385988, + 1.5979034036313131, -3.8353239436016064, 1.9302760105322174, + 0.4906948818786122, 0.8236304101051184, -3.808384325093473, + -3.0486518743757527, 1.950339059255233, 2.8772324445470883, + 5.748787174063801, 4.506554717027688, 3.3188306684877382, + -0.39989321009171214, -1.5738329587862223, 0.8952788762998415, + 2.137591708106581, 0.9465115280495907, 0.05176049572996668, + 2.649712588418019, 6.594377339599191, -0.6593129867093952, + 3.4751822144088056, 1.4732219752230908, 5.704914737143688, + -2.0579211773330077, 0.6241604121733543, 3.5941317673956266, + 2.2980594307532347, -3.9327004047025476, 3.2251181402296454, + -0.8913391361706277, -2.7466344743809117, 1.6619318036068254, + -1.0500979205665155, -3.0351188482866753, -2.817952849035236, + 8.918295682184953, 3.060364669625106, -2.655530445833815, 0.641848597267752, + -1.9681102112267448, 8.525813146195036, 1.4343982755532703, + 8.908466876353918, 8.590443320024665, 2.711023131254724, 8.89947385113805, + 2.0939160057034907, 2.65103084662334, 1.4626356674124337, + -3.208343456221911, -3.394173167006077, 1.932850927448628, + 8.805758171186842, 2.1243490534911382, 9.028296832464864, 8.937647726199716, + -2.676577582815389, 5.903288211290661, 0.6846977509561695, + 3.8156052421272375, 0.7634478610334001, 1.0540467411943064, + 9.699583427222773, -2.3747586336050936, -0.95596567080788, + 3.4920439930271123, 3.11235139509691, 0.9378696639670594, 3.35621409897869, + 3.679262467886785, 3.2029311363539437, 0.8203047778014468, + 8.554043310004833, -0.42993598576078784, 2.511692309884933, + -4.756775876827685, 2.0603485204111323, -5.337213657671816, + 0.41725336047678596, 6.629983319214528, 0.8903099477880994, + 6.183510404022067, 0.27046258864924877, 2.8507973745983386, + 5.953930731914141, 6.667463064136371, -1.1853152943830194, + 0.10929547791890014, 5.159454256150641, 0.9575382360439176, + 1.0472819291348658, -4.478812598974675, 1.63438677088275, + 1.3966105306914227, 5.436410376920915, 0.3892766858938439, + -2.2905961508012016, 5.229602809963853, -4.864452941250325, + -1.0538101708637058, 7.164793904682805, 1.566138730677346, + 0.02704482509077386, 0.7886677241533953, 3.979684289364822, + 8.562397301181349, 9.285407951263371, 2.0223634080105914, + 0.6748346443384347, 4.836315638695997, 1.9106703975216532, + 0.5866544286142371, 7.697482947447593, 9.036618052460097, + -3.3937610246659538, 1.4695633885567845, 9.806593022345849, + 2.803053620065441, 2.79080811918104, 9.085897942228886, 0.20786152462408714, + 4.554414906944457, 2.2687730874822374, -4.4758778295507735, + 3.01749403025241, 7.009051356750071, 3.301496781305262, 1.5978822792179508, + 3.507883946533327, 2.475904595046087, 4.723309718269045, 1.2999810793281195, + 2.6994776633835635, 2.1776105906692953, 5.636269224455179, + 9.227390068887006, 1.6653064746540052, 2.531245644163319, + -4.796726394177121, -4.696260149586186, 2.360303171044659, + 4.809360672005284, 6.792224681851225, 5.0239174109239295, 9.758115953321388, + 1.7938014075697666, 0.5624509627239803, 9.136243614649574, + 3.355605586871464, 1.5306096828306694, 8.536995394913296, 4.284406786162418, + 9.288709095420277, -5.409560336785602, 2.964373643784957, 3.7541139426875, + 0.07436249434529059, 2.6543557259993937, 7.326068587028396, + 2.361487178667938, 6.089912059689269, 2.3291514353075016, + -2.5797469891430884, -2.204272569458718, 1.5814138070450303, + 6.603394036525644, 7.97166923117362, -5.421796406778391, 2.310834537661771, + 3.83348926088483, 5.924444956089124, 5.705844596614569, 0.14904642961421793, + 3.2627918032804986, 9.156346620095126, 2.3018313060026943, + 2.871420436775351, 1.748071777193481, -2.1699630188713317, + -4.423588831601064, -1.752210329525351, -2.3332531026084373, + 8.078537148930103, 1.7468782968550507, 3.870771091266975, 9.570067082920405, + 6.532531074910839, 5.312720960762101, -3.3929967864383554, + 7.086090345521071, 6.218945608429214, 1.8768890922016566, 2.607564369570601, + 2.7622849353834233, -2.5914874773514547, 8.198193747137957, + 2.989820306813261, 1.7633582516145228, 2.9524698537504466, + 2.9608279326797815, 5.159943485109591, 2.258405427983319, + 3.3374602636934623, 3.0273792858264996, 3.1487351190544213, + -2.4495969677949208, 5.929783834857964, 6.711771007305786, + 2.081925344296031, 5.877244018303804, 8.886653410012418, 0.6264009865824708, + 1.114324963535137, 5.582000655882144, 0.10484985819812484, + 3.9844989239986037, 7.045339331126441, 7.376022206417836, 1.237898376943498, + 1.7470287460799372, 8.605965387841337, 9.617446675860762, 6.882498231126236, + 1.9704705198454397, 6.000954757287207, 8.630755642486054, + 0.4865847848937903, 0.5890115071805289, 1.4217583119146444, + 0.5759370890401244, -0.9918362868258609, 8.505381270758573, + 5.205225724209531, -0.1641339289559732, 4.271545367645099, + 8.773787765364231, 2.8341861182864894, 6.291040395037355, 5.433244854956153, + 5.102936340570758, 8.422552614349282, 2.8196855273663104, 5.678926500302951, + -0.5383477536287377, 9.4253523750977, -0.22856265846694768, + 5.45239998827267, 6.874084499868811, -0.18137759959854494, + 9.478295589662668, 3.431633175563881, 2.643320466978511, 8.186081903820728, + 1.1989638010195498, 8.54718584644179, 6.557128513378248, 1.2300152894799241, + 4.51921956332824, 0.5693115943422644, 7.553359478391619, 2.893921560929296, + -0.7541870943606744, 3.4344316370472177, 4.4779116179245815, + 5.302441643354457, -2.439565181008059, 9.512899428908435, 5.385826259956362, + 5.908299075924965, 2.100513563369361, 3.3266700309599027, 8.089733332102341, + -2.6243622656468855, 7.230528970232492, -1.0218346404298337, + 2.5739332556555383, 2.4854245355736633, 6.832761487018405, + -1.5149844127528729, 0.9201408348610742, 2.1035468063646627, + 0.6368115250012512, 8.214982113070004, 8.918916811304616, + 2.7106941171332286, 3.8123959687632794, 1.9182183558652177, + 3.3011590899178067, -4.268458134039248, 4.1607923908684805, + 2.5607637404629346, 2.537623329117577, 6.203676444622138, + 3.2449911641283866, -1.4863704718561914, 2.0914264281124773, + 8.866073437504284, 6.360534894196076, 1.8548388788418777, 8.546565459118982, + 3.8121042191991363, 1.782761627693268, 8.19409331440138, 7.271377077104276, + 6.713834371576997, 4.7054015736273005, 0.6900279581442493, + -1.9950523194654137, 0.5019672047701859, -2.4425971792925014, + 8.397284515101749, 8.274477379414355, 4.320281308205884, 2.7306208965349557, + 1.0268803986720851, 8.041844717647683, -4.865558143399747, + -4.43090033274667, 2.080138753512541, 0.3985237911488679, + 0.13915356157220796, -0.6797187918311256, 1.499451661991291, + 3.1062195316504724, 1.534350188556406, -0.42490380560179697, + -0.8824812983295844, 6.137019298389204, -2.442387086532495, + 3.5302750806073444, 5.623701737032925, -3.048559332327405, + -1.7927761727406366, 2.2501008966231493, -0.0434390996019198, + 2.0713629857341833, 0.6667391023716165, 7.138508838403462, + 9.117134927041638, 2.844253892877252, -3.010065734551748, + 5.3434391962662975, -0.03387006007417064, -4.321302231073703, + 6.015578668701478, 8.694611177352565, 2.840831058685417, 3.590468322991271, + 5.925869307767682, -0.4632539232111991, 9.852085447425996, + 4.246050458490948, 0.0795569848871431, 6.342863222998658, + 1.4051373647168843, -2.1635570082088544, 2.2571055692634374, + 3.578015263178784, 5.92501466937786, -1.9992269400077587, 7.613431338304448, + 2.0586657648069444, 1.7131255525320113, 2.850162142184762, + 9.387208612221631, 2.9743469463435983, 1.1035216432033375, + 1.5082199385262602, 1.1770277270238634, 8.727374689487656, + -0.5503031034740972, 5.996322472782943, -2.106014886932281, + 2.7145712429255298, 2.959255404634817, 3.113836493861464, 2.769285267659297, + -0.03383966505561062, 6.981888952467136, 1.987340238395796, + 2.5935349892602932, 0.688685934326811, 0.6023938118323606, + 8.280187749951624, 8.657520654006337, -4.614428004690138, 5.490273423799091, + -0.45654403516637426, 2.2552766262157378, 8.950763875630653, + -0.752654576519053, 6.198515988684498, 6.375645140382823, 7.778627264011731, + 0.0679528135196061, 3.1097816129485856, 1.9708437429931311, + 1.2519087257185952, 6.035823894471679, 2.641606741377335, + 2.3611442950292063, -1.2138498292937214, 5.848272228719679, + 0.9787762749408776, 0.7896001910941994, -2.9666200974972514, + 1.2153395327671428, 8.51216629567888, 0.13161855421830565, + -3.1983695913395485, 2.4048892802020774, 3.2731024798000132, + 5.892377898027779, 0.6485778189416769, 5.531378659573957, + -1.8313893011262574, 3.462656522250383, 3.0240830103191456, + -1.3988666551884819, 7.196571559897184, 0.3669345964179366, + -2.8035394109630563, 4.692363004269288, -4.476727261762838, + 0.32343844200745103, -4.182356703599284, 2.928534228041603, + -2.7685368080690473, -1.2654701804392694, -4.052775980189864, + 2.6577769067459074, -0.9883034373434559, -0.3934847099090396, + 1.2274252023207477, 0.1772146684449812, 1.4914482504911268, + 1.8188586228106742, 1.5897815313464005, 1.0307870297513482, + -4.552732358353905, 5.596899036377971, 1.1599206410942584, + 3.4385418183942993, 6.082213341527612, 0.7341908164143667, + -0.2480626007455346, -3.1575191950472297, 2.5389293824676726, + -1.4003061229056613, 2.6833282298497223, -0.5467975634173019, + 5.98852696995778, 0.21292691886096327, -2.6893512720716815, + -5.117588668343177, 6.794322180635246, -4.5742625010613285, + 3.3548586996326435, 5.0515600035370225, -2.900449599496725, + 0.10237610962475915, -5.064851833194207, 8.531627029244655, + 1.5742438748697312, 4.082638432652501, -5.0770992768786645, + 2.119205675069604, -0.549498327530717, 3.5730581737051277, + 3.196962670970756, 7.035845030498391, 8.548505437332542, 2.678325032018049, + 2.171957067852686, 3.4355159234823076, 5.376546760599714, + -3.487535293579003, -0.7959857552014767, 3.109184499044637, + -0.034074417858167665, -4.463432440942218, 4.754451040108373, + 5.977086152281335, 6.3113939537838615, -1.1073355025666125, + 8.245632488073356, -5.2333112598995895, 5.178870586953865, + 0.6180633531176227, -2.26460261809812, 4.353674921953694, + 2.8072255410103386, 1.521416200823173, 7.589366619945358, 7.701394142184665, + 1.2116731292036584, 3.2138291408691844, 2.8443169344773516, + 0.8903178116947174, -5.108687151576169, 7.717847243550239, + 5.103365026900776, 2.2950781198168375, 6.397420501802669, + -4.784056687598436, -5.164879189057719, 2.612616948933114, + 2.368955342992421, 6.57506537945875, 4.983841437905054, 2.50680520340803, + 0.9418427383823713, 2.346670739637181, 6.7670420058449485, + 1.1729036494953344, 1.3973552011354742, 1.984364716958311, + 1.1219650572007647, 1.854444243223755, 0.15395235570302412, + 6.207396756273517, 4.902381553967024, 4.057220866025185, + -0.1327819842430041, 0.24745711201195134, 6.1793343047872735, + 1.8642901437174684, 0.6795484548721835, 4.802713069866874, + 2.192594562354952, 7.504825326157448, 0.4360785367712627, + 3.0969826788534904, 0.3149099546820246, 0.631302944620672, + 4.008347085568968, 5.796200617136318, 2.690265077072964, 2.4509671492071647, + 3.1794303634347654, 5.480282099311519, 3.793009761585952, 6.694411441476124, + 0.14085170243202885, 2.6005776440097637, -5.2332737609043765, + -2.9808615128824476, 0.8786289985481496, 1.8675196537055403, + 1.8798070856567528, 2.979399276715977, 7.348120227074838, + 1.0545657973863674, 0.35836880076700756, -0.26505513627447935, + 8.37604052125493, 3.8108946951851164, 9.371530125128047, 2.1527731861407666, + 2.22024217006518, 1.0043860933717168, -2.8223649837661275, + 1.4529377327135113, 0.315286921325931, -3.759919055529933, + 3.192557001334405, 5.99258651557055, 2.8135841369438124, 2.835625816399913, + 4.784946846678241, -1.7062587841124341, -1.4443605566411828, + 1.599719712031716, 4.626872133922204, -2.066200466458587, + 3.4202402597721107, -1.9258775472193792, -0.7109237030323599, + -3.0633148300714814, 0.7916130122573279, -2.8003481525863623, + 1.2805196495791191, 7.641070031410805, 6.899822557600844, + 1.6947028912538717, 2.5581600518961483, 2.0034929243649846, + 5.857911263653215, 1.4636246547379912, 2.8971993456484375, + -2.251511707977432, 5.884447799046445, 6.7644617214749285, + 2.4674566860698466, 2.399380076812881, 8.639067607097326, + 1.4161103959753811, 2.655889404446979, 1.8657322395014868, + 8.099395562761458, 1.2882372797576638, 5.344775989736017, + 3.2843163197624916, 1.3268692580615533, 0.8743822373812074, + 3.4891420513567053, 0.07385661891207071, 2.922503933319907, + 8.714379542426268, 0.6501668013700235, -1.1375008855416793, + 1.857754709954258, -2.9945232842258678, 4.684544304995022, + 0.12886049121117665, 0.03972938223109909, 9.237892036506507, + 8.51762483804629, 3.3724974386724624, 3.5329200482619085, + 0.8927369288119711, 1.098034894330614, 0.0766899373263363, + -1.5153756903132682, -4.859313173242173, 2.239424598692307, + 0.3087161707098317, 1.4471925711686535, -0.690409487135307, + 1.6160860392915781, 2.7508251678939137, 1.688227865698469, + 1.8258302446153771, 1.2362379094640268, 2.227100763719389, + 0.013469605778813766, -0.2565112959825642, 2.3112040766131825, + 0.6319471784615154, 0.20327688152306575, 2.604414592341301, + 5.66856972968723, 2.7980140743746076, 8.67085362838519, 5.918440790189692, + 5.7224556859282, 0.857285364668508, 5.544811900362975, 9.4435138232807, + -0.20236353549092811, 5.016793650411961, 2.720699822325314, + 4.5479069977602204, 2.715983316290806, 1.7525824693752088, + -5.264974061070002, -0.6496290315234062, 2.367614338923079, + 0.6879917909303833, 1.3029286630363872, 3.0138918746597065, + 6.640804353774791, 2.7172754438040307, 5.76419355748975, 5.017375178348365, + -0.10816025840842662, 0.9453881730249583, 6.720643124414721, + -0.1103631054118109, 3.3408766939456034, 5.794047549702596, + -2.025824021148328, 3.252234698808337, 5.530672000744878, 8.64747695134738, + 9.515097696825404, 3.2344927992474717, -4.561284055904563, + 5.603927007833755, 1.6239964904833328, 1.8190481024621308, + -5.303239347416054, 3.4400884108742207, 2.076151202158285, + 2.1590840988805513, -3.874933358494983, 8.009236378478496, + 2.742251873418243, 2.4574402301105303, 2.1704695708632493, + 0.07441695251940642, 9.142691879015315, 0.09950685263139657, + 2.547726388955141, 2.4264440031043555, 8.995420023183437, 5.928160199896791, + 5.10369858225642, 6.797099162610654, 9.891558600174584, 1.6271653661516037, + 0.865228175916761, 3.293969600310039, 4.5338781574902605, + 1.8576515517527716, 2.200264025873621, 9.229541062816832, + -0.5258640404899334, 0.7878662950097198, -4.809662866623755, + 6.172140436212999, 2.353632835509077, 0.3245596351457882, + 0.7492161994440059, 2.6243550810331664, 3.6033101201399518, + 2.883674831846493, 4.777864163973319, 7.608122293011118, 9.094148010265082, + 2.8586547600235472, 3.0637538813442333, -0.16306496309051946, + 5.978283707847633, 7.0152850555910025, 2.089439744209332, + 1.2699966622815706, 7.632606479355867, 7.426884733347851, 4.919860769652532, + 3.4636433196516427, -1.185439361099015, 1.223042401715309, + -1.7204930505004916, 1.2498940606612439, 6.096280333402219, + 0.0255562791229087, -4.7421129527816, 6.9134628087321275, 9.345092400602578, + -0.7428833847718531, 7.751469449471995, -3.174355411099064, + -0.4389593568137036, 0.7889164889254271, 0.42671004071595564, + 0.4146530713836919, 2.9852951657239575, 2.420596392633052, + 7.280976775617019, -3.9833538656439123, 1.8123279460938362, + 5.254191706507663, 2.988686456685128, -5.122771852329393, 5.460160945532948, + 5.556392417120963, 1.1989693659532146, 1.8856338222888531, + 1.4304240447047571, 9.103673874712799, 0.06974033136878711, + -1.8634596072735357, 9.181488312562077, 7.782179970735101, + 2.0106552241346183, 8.423518536106023, 1.5602445629709538, + 8.192057648102823, 1.166091512538277, 2.924903190780516, 5.805348422221177, + -1.870811325838246, 5.497133289900674, 0.6912014452029617, + 2.4494309050757823, 6.214442790508838, 5.532218926098756, + 1.8484648675848672, 0.5357420048696545, 6.168881879285348, + -4.164441414751242, 0.8497563909106339, 6.068046616819917, + 1.6311217190066913, 4.935653352145963, 2.909436523764689, + 0.3586354983898887, 2.6396021300049144, 3.4768890569507467, + -2.888866342024628, 6.580642289649002, 2.302982426221136, 5.055472805495961, + -0.4836179568565782, 2.6416319996966986, 2.3803682290271317, + -4.975249596900043, -1.4678816639945595, 6.54720672263416, + -0.943030719721922, 8.06944049964118, 9.456410932217949, 5.477892548341206, + 2.0069868969636064, 0.33000045858721744, 0.45137009084748314, + 9.585272571025595, 2.6585240479374606, 0.8401318359631659, + 5.921237265866324, 7.0614974156154044, 1.3234965998892707, + -0.19082410082550832, 0.9482892986162604, 5.1980514735827015, + 1.8648414428434004, 3.8275970013636003, 2.145441639200901, 7.18545866225611, + 3.7681560899027025, 6.7706972228375815, 1.710843392703091, + 9.653896454935389, 8.991595342866164, 9.186382157891034, 9.04406304944811, + 0.8172915176930347, 2.7566256486526353, 9.660910576572753, + 5.774924628332689, 1.0341297924498363, 6.776970079531831, 6.870337511570097, + 3.316407570037295, -0.7327186727816404, 1.4785073400784159, + 3.2646800316507143, -0.20914306937205182, 4.64867840898082, + 5.091437827560491, 2.543828629721811, 2.491519287769942, + -0.13127409974118892, -0.6849444346996574, 5.704748046506554, + -4.580428758802872, 5.9276986115834305, 5.949946091737831, + -5.112703533067682, 6.328840062412349, 1.3725722459483412, + 1.484950850899703, 4.922692136902319, -0.26360087335294413, + 0.3972863993323734, 6.43499018390537, 1.9261614464785353, 9.25217428814158, + 3.4887977439401117, 7.798413137478559, -3.859332588932147, + 1.0076305806755113, -1.595328104377359, -1.9345755656466876, + 1.3656568430290457, 2.010239600296628, 3.0842970345182317, + 1.8307019509259435, 2.5249665379978907, 0.21114084691696372, + 3.010763869995198, 1.5804254258562025, -4.520042320218686, + -2.128356334095731, 0.7405047744804988, 1.7154819971091906, + -0.8522515684542971, 2.442382303303678, 0.18784706156999456, + -2.109265073450941, -0.45500559588426437, 0.7348284376716618, + 1.7123931297303872, 5.254688512601999, 2.7456168285842244, + 0.5416658212070915, 2.301238469829127, -3.1464762215917483, + -0.9007639718009747, 5.42006148595848, -0.9861660783712057, + -2.162965897976326, -4.493082242249678, -3.8189365772831603, + -0.10234080732201847, 3.8222780518158883, 6.069040078680538, + -5.257236694544421, 4.043152750327152, 2.9400998090483847, + 8.123198210212966, 1.1001939822886846, 1.2565680855375772, + 2.245798308281623, 2.4479921134731173, -3.158270658414151, + -1.5481370872038624, 6.312918687487506, -0.37121749047904795, + 1.6919954011846836, 0.6875554834459174, 7.242510466143665, + 3.2722108293917302, 5.8160212902859705, 0.26737489698121397, + 3.0063850526444735, 3.506124855697979, 7.042641095704005, + 3.3569127880879672, 1.5852174746984395, 3.6751882693142797, + -4.165220031935649, 1.215199283565774, 7.90308322296078, 1.5939925329095328, + -4.664195921536808, 2.4132307103650708, 1.6273049780055568, + 8.030453359488645, 5.926901407210981, 5.96945226815641, 3.0528213692017427, + 0.5294928795205264, 6.111198931739082, 3.27826803975091, 7.979729831606848, + 6.579075127990691, 1.0644579389040314, 3.102471494981852, + 1.6526255527926923, 1.7127900541239869, 8.283760640459029, + 2.1924222459051204, 1.900806515428295, 5.329619827785321, + -2.071511831927549, 2.1229332814500315, -2.4852779587449625, + 3.4704642694533496, -0.37053887420146553, 8.385984728405884, + 4.493223761008627, 2.180319410350078, -3.01208855357939, 1.332983186514152, + 6.130263721597461, 6.9534807344215785, 5.88853010829384, + -2.8407853967671577, 1.8033610815004772, 5.949222221028675, + 1.9889057182006664, 5.176870999104773, 0.9709025783457912, + 0.4775110339612653, 6.003172783895949, 1.1595497820232883, + 6.039896301978691, 8.88875053895144, 5.660666726152205, + -0.20707853144034163, 0.4656841519810458, -0.46729412109856766, + -4.763487218056729, 1.0575797208447806, 1.4690708457781543, + 8.201368891883424, 6.322509791870492, 1.3428277584119488, + 2.6268228995812533, -2.021077629389779, 9.536296205942017, + 0.05281985636909039, 5.667685369387791, 6.0217023360515896, + 5.878501643642019, 0.02298604850952251, 5.729457157547902, + -2.2733129918903487, 7.357345572460884, -1.6602227754960404, + 2.8933777470936346, -5.300255477680182, 6.674143746202342, + 7.354433017740983, 8.32057151070352, 4.986715253364944, -0.8236511115608395, + 3.000653918731319, 5.142268479074093, 4.991873612764421, -4.462314080258194, + 1.4099959224940581, 0.5140333598695296, 0.462038563308794, + -0.5580698037160144, 2.4156214850354365, 2.4150056047346644, + -1.4348713625629237, 9.37189601203025, 2.2128480268481603, + 5.501830807729627, 0.5970505131245347, 1.7086361564802768, + 4.966871116438676, -5.51059720745767, 0.40783914628227114, + 5.655657432376619, 2.1835504862122175, 8.168986002754655, + -2.7193188251020834, 9.398775404415085, 3.2418349793456707, + 0.8676509750580216, -4.113737353548256, 1.024007404044521, + -0.34756324082994794, 1.9602376164792763, 0.7832705087881328, + 6.335484216782878, 3.848417262983378, 2.789319415517467, 2.7804749683831655, + -4.209835262087807, 2.134517779191862, 0.20877152273204996, + -1.6896473650266692, -1.2400823830799401, 0.8168266270138272, + 3.003065455584158, 2.2137576704758306, 2.3334723718138632, + -0.8022301886454714, -2.3591277338516994, 3.269962993932029, + -2.0834230276898755, 0.9951956155368633, 0.9691860719679056, + -3.888839739561202, 2.1629207058674904, -1.905675289518531, + 2.69453691444355, 6.701800635735289, 2.5725594382816372, 8.588496425207529, + 4.7106805174377735, 6.410515675188265, -2.6226997711629716, + 2.072002183326608, 1.3526862546035745, 2.1997548005471264, + 2.526355377006503, 3.3454645401850533, 1.8236407076363763, + 6.637010415903734, 0.6187101895208668, 9.301085778983579, 7.726784389543951, + 0.9099830270183308, 6.722528024137925, 1.256374452711205, 6.793998223541745, + 3.0663208923461376, 2.462996441838422, -1.2483010887074464, + 2.4878297941421663, 5.988784487203425, 9.308199852291192, 5.883351018668258, + 8.143463243475388, -0.8356458655755094, 0.5497825145679909, + 3.236547594377735, 9.029397780799197, 0.22996970906321432, + -5.012819578978871, -3.8497149088058915, 1.7755407000814296, + 8.59826241534019, -0.4075788598887008, 0.5821111590672242, + 0.23063765524325244, 0.9189563098666551, 7.232389094906414, + -1.268420609294997, 5.7521552238840465, 2.203239339828908, + 7.005547360934609, -1.1313653909462507, 5.67130135575973, 9.377013452063188, + 3.4162063856020475, 6.891357953756193, 5.572513194602001, 9.616751460142105, + 7.3777860186219915, 3.5562906047735603, -4.282360119923921, + 0.6698010007632262, -3.2554024637200842, 0.29250443938453025, + 6.425718881533466, -3.177602331295984, -2.454493843289483, + 6.314811684076483, 8.979560158834992, 9.870736213896537, 8.757264493637411, + -0.003453712350984302, 8.817969535806293, 5.843733799478246, + 7.054684804368724, 3.1919023793630075, 2.699640057234987, 2.141516681314163, + -3.4472292168477012, 1.36908126062115, -1.9441012592167115, + -1.9236197068234189, 5.397184307275612, 2.0757701792890675, + 6.778390763843739, 8.443855120253565, 7.08532983610067, 7.9608745265204846, + 7.225488139730609, 1.845551458086398, 2.6478648952083716, 0.699909602488156, + 5.578408909149145, 2.3707672322763456, -4.360423816613405, 6.34034815381996, + 2.5123983953755586, 6.234127752856539, -3.403233447929865, + -2.6398216695932124, 0.11824856949582217, -0.4560083455354007, + 1.3623351137161217, 2.488437018998219, -2.0996984449895026, + 0.4529341843863447, 5.7316943952319965, -1.6794395006623484, + -1.662952700628585, 0.7528252276279854, 1.86526470435675, + 0.8250661486800847, 7.545149459365755, -2.9784914139412986, + 0.7955122992388768, -1.749696914354937, 3.007033532357639, + 3.2539694960317154, 2.325020884091079, 3.0682380835267087, + 3.4877633370885603, 4.755907494880818, 6.128266753985117, + -5.363081889079644, 1.5887297020473807, 9.505091939439223, + 4.365143981465876, 6.7548503826243715, 2.5052979166231886, + 1.4353576508393462, -0.9928554982734809, 2.922494124533855, + 8.10081092078275, -1.3002214585010545, 0.8404824712467401, 5.94837787669559, + -4.767683732401647, 2.0017751275916296, 7.915636914038291, + 2.5822586807239722, 2.8495043174738024, 0.29281685345900793, + 3.07193328710613, 0.32780731449595507, 1.078728624062782, 9.212142393190357, + -3.234096488944491, 8.99985503777453, -2.855040830930229, + -5.295863603354861, 2.9629710484192806, 9.59196741817357, + 0.7743349776222785, 5.792043147303167, 0.7308440213299643, + 7.350415660821069, 3.495075238229184, 8.647182976752868, -1.534758576855379, + 2.073463430160869, 1.963332441387051, -4.694354180861564, + 3.6714354834316927, -3.9262388559123464, -5.546500365026073, + 7.445083723470979, 0.5343682186596866, 3.183237056362217, + -2.403816101636754, 2.8857332178958295, 6.672428835630001, + 3.6953141788532005, 5.29590329943819, -1.8554545565340235, + -0.17610077417452594, 8.271235986900548, -0.8302414238237459, + 2.4378481735230384, 9.57202802197544, 5.557141877865675, 6.5268978634694035, + 0.8407924426877699, 7.979052578435055, 3.117590024813628, 5.96352037754916, + 2.094825703273501, 0.07296691179388555, 1.8079190555258078, + 1.7205218009412788, 5.730311841139373, 9.168679321911021, 6.63794178471708, + -4.770023224802359, 6.32579824811486, 8.060919532649441, + -4.3498104635619965, 6.056146366036844, 1.3888378059597648, + 1.5681318199046925, 6.934114111947524, 4.553233986454347, + 1.4275240710301833, 3.747256941001211, -0.7793987571499036, + 2.4159574731318942, 6.360954669715619, 0.4084551726607402, + 1.7502096715103717, 8.32356944907215, 9.411852540453843, + -0.24749985885791767, 3.6441437548002984, 0.6638796329985154, + 0.49554468852439093, -5.288299956200278, 1.5867630719594317, + 5.266978763389619, -0.1730881110987882, 2.027850474654688, 6.70043355578779, + 0.20699152625797068, -1.4169490537802918, 3.567763215349293, + 0.2333312464661514, -1.4878662123333741, 1.091060642589443, + 2.4017502719866424, 7.9782861690822, 3.44782406334824, 1.0432269698264383, + 4.640994658240865, 5.749646077991115, 6.089790596813214, 2.9853600065784107, + 1.585551391839002, 4.403944696472623, 0.29951265146255124, + 0.24389931462395698, 0.8540781982541754, 4.611025267027386, + -0.45181284082359413, -3.5542731441518876, 0.20103598685438334, + 2.3975234423332497, 8.6230597387424, 8.663118774999928, -4.529682685118797, + -0.8760724945413672, 0.25604543050627254, 9.032110091018815, + 0.19628068798147708, 5.911953902186222, 8.11065712561067, + 1.5106611736082836, 6.483990941242417, 0.9154031653035811, + 0.4733209855793123, 1.2729172153754813, 6.226232576039953, + -3.7857216516839913, 2.85210708040812, 2.3947148486545013, + 7.649662954804599, 9.16162216363764, 2.2116236694661873, -4.445492844370273, + 0.11508527097851792, 9.076362458267964, 0.4348146585260673, + 3.688186838147284, -5.321770884683309, 7.415460097453132, + -1.9534807833504129, 8.50852643998329, 0.8570152188041182, + 3.002819999704473, 6.0288006491872315, -3.2528245994908955, + 1.425515401254983, 2.518619468789845, 2.6021768268562155, 2.414457971274285, + 8.811798173197223, 8.463135654386775, -2.3599709268161466, + -4.470741594770652, 1.9029054733785435, 3.5107539529337575, + 2.517914528908818, 3.2373739399765995, 0.9559242825654067, + -1.4022193331720425, -4.164011090781615, 3.5098720942728066, + -1.5152128618720702, 1.2042015283823664, -2.5223273022794563, + 4.6568722554070785, 8.748779660690749, 1.64867887605269, + -1.6451264272207415, 2.223501415745643, 8.983241413406752, + 0.7856413355998099, 8.271058597380113, 8.759786053557635, 5.964851993500417, + -1.9854392851535787, 5.417165541146182, -3.6442197852501232, + 3.4828188869815073, 8.467767959705135, 1.2727275656548527, 8.52188240945984, + 1.2193859287039661, 1.6753573505177883, 2.7578999432181828, + 5.752416727518017, 3.4895594687669718, 2.848717380504166, + 1.1007765674235717, 7.3936145172341945, 8.335571225152114, + 1.3472097319919996, 3.1371705224091144, 0.4215143657193758, + -2.0292815257034817, -5.49035861680535, -5.183291470456518, + 1.8343121382967842, -0.30212063468598305, 2.67347488141855, + 1.2506741064376266, 6.705326698795701, 2.3117777668167516, + -2.166111449868967, 3.3066654185985973, 0.8743752567181792, + 9.433552236501237, 1.3666782032393632, 1.130142268909575, + 3.2738566103698905, 6.5968220577140055, -1.3891345838746347, + -3.5128981904432948, 5.0804414422022335, -1.3058470702411964, + 7.130933426715227, 2.4273980019954204, -2.1608284982186197, + -0.9100596860292837, 3.5894835328702106, -4.751280916256097, + 2.569585024243075, 0.2919735183319088, -4.406471808552807, + 9.003775888319385, 2.7525231897174263, 8.491374502683652, 4.376946832713647, + 8.527523053929686, 5.632602084917159, 1.4052219593748756, + 5.5737253668239655, 3.4569678545306575, 2.8171500161674357, + -1.432944115552822, 5.697969375029198, -4.621445460935588, + 2.0787510016080533, -5.326683128959758, 0.18067104116133456, + -2.502498411746137, 5.629349911367992, -1.6890235276676102, + 3.045990978436232, 2.068467399984089, 5.084093781542543, + -0.3929337578092091, 2.5605365794849444, 5.53869708350438, + 2.614522456632436, -1.5480239773209241, 3.5678945576150123, + 8.83401771512541, -1.5963844207514608, 7.624379929762122, + 0.5005540393521262, -5.527784938566744, 2.65125893195905, 2.130758952863588, + -1.8332809453947294, 9.30394757121743, -1.446331856826678, + 3.2165312128841435, 4.04687189616058, -3.5056213436587336, + 6.666219551384144, 1.3673469667147284, 1.6231652648575179, + 4.4948549236610305, 2.0815856253285214, -0.60043979994161, + 3.590976451375838, -0.7453152161686788, 1.564348734142829, + 5.541589960918232, 8.202930465965972, 0.7444615247059749, 9.587703248667736, + 0.4935395980500209, 2.02135191370068, -2.63757568386335, 1.6931078983944303, + 6.194891401826324, -4.755698900045702, 3.053941263428849, 1.738035826808363, + 5.482444085458718, 8.578249176772534, 6.622930301440895, 2.125057661575636, + 0.9054222604976315, -1.7109375809695786, 1.4198761476337516, + 1.054867119727166, -3.925252521521188, -3.0436012570906885, + 2.4145304719634875, -2.7089004374087096, -2.5781187088980415, + 4.040219917034839, 5.7177319240579125, 0.41648218881027665, + 0.5737150782632761, 1.3605157350455324, 7.762686896051611, + -1.890859886923358, 2.9869526962840838, -0.8018564162424652, + 2.1407876001056168, 5.863579989317062, 1.1422827886056979, + -5.034414504153599, 5.306443885502887, 7.855634915825041, + -1.840671726488353, 3.1453425959097934, 9.521053083576877, + 1.1797955103350146, 8.34289646049561, 0.9864026286857854, + 1.5511568318528561, 8.434271139212683, 0.20427819364048902, + 2.0271112325590077, -3.9356698611216534, 5.870340206181536, + 0.05269352565779371, 1.7920616044663369, -2.42138548840195, + 3.475007131820548, 7.011108331408282, 9.515231228026291, 6.346792668752203, + 6.494414623263908, 4.472927613760124, 4.524003924372726, + -1.4134186597873823, 8.723691479901538, 1.8639456444607319, + 0.7382556576116613, 1.7673853588875232, 6.396387432623712, + 5.591000021046794, -2.2765896318071217, 6.2962062739823965, + 2.4212794737100123, 2.697188160050856, 3.5064505365695777, + -0.9661428559971644, 1.1653071361402214, 8.832158933958235, + 1.926594996120538, 2.2382815782643033, -2.138572477012913, + 9.020160211222818, 0.34070599225005027, 3.3797625149541055, + 0.05703965444493409, 2.305032462030537, 6.2463349336626495, + -0.6584707349200902, -0.38389619151492244, 6.120169056030916, + 1.6388345686915071, 2.205438800430803, 9.043723892497786, + -0.05324007737301528, 0.3651143038587914, 7.001822659426594, + 2.5765444604895604, -0.04862648951907117, -0.8854025072266365, + -0.32410129627632506, 3.0812142492739736, 6.295356520537049, + 6.177967110174736, 7.079564521405287, 1.83353114343839, 3.2388910348859192, + 8.913712343332712, 2.4375146713115385, 1.2634733710281858, + -4.414938136285208, 3.4759377909794242, 6.569247134786052, + 3.3257450358478975, 1.0495790550303425, 2.9650735879571166, + 3.4456722296078293, -1.9425450759671543, 1.599117095043776, + 8.497017451637193, 2.6579556546365266, 7.910087173332323, + 2.8799774369661812, -0.07025037126624543, 8.073942200277664, + 2.3342142619361534, 2.8830916269966758, 9.100411166653252, + 1.2058185139176982, 2.675872700135464, 0.9666762827582379, + 5.616586906563049, 6.905637710372154, -4.860074337814643, 4.0158954528166, + 1.0941869678450136, 1.3322841635744591, -4.8525029564210955, + 1.6950143873386676, 2.275866960775223, 3.7546696075480233, + 8.522580158693797, 8.479289443791219, 9.084376204745716, 0.524887035594922, + 1.7930496347425775, 8.36265519445222, 9.13207967711533, 8.728248933808025, + 5.104280192568869, 6.932520932186675, 6.57954219836973, 8.358960821108504, + 2.5870592720871555, -1.8119057173172903, 1.7265071935675682, + 5.343747915510189, -2.5904371427923047, -5.105623763927343, + 1.7555879054859012, 7.85831749823218, 0.3955986367670087, 2.693545835650025, + 2.2783352602443867, -4.107147221405172, -0.3589112571594508, + 0.2739780970973445, 6.00113681801525, -0.9520046557887152, + 4.455509206119695, -0.07994742403490834, 6.912346070734264, + 1.7374666740318419, -1.9482137044069845, 5.243596178912719, + 3.718827522220301, 1.1880164187237157, 8.047695963346682, 8.117318312531806, + -1.5085045180979209, 8.80835524866147, 2.9999212372772712, + 5.458046876567976, 0.007803281932174618, 1.3849554785538867, + 8.51477432156869, 4.656161890950504, -0.49453412636627153, + -4.9425646575433895, 1.5754507134189302, 4.071093984813563, + 1.4821345261234662, 2.815670718021292, 1.9423374489222467, 5.64234093990883, + 1.711516119661729, 2.5246316441116576, 5.404768257953342, + -4.933144619659127, -4.0862479358951616, 2.414531419272294, + 9.27182973316845, 2.2064135982664714, 5.872298049989269, 1.4429082064623937, + 3.99304417572891, -1.7976779555774933, 2.8060601507477996, + 9.544330963742757, -0.2234861369430893, 1.1926141918363296, + 2.8595940374636495, 2.6911712476226657, 2.458521202978513, + -2.694375476554727, 3.9776603483448296, 0.6718385790624146, + 2.37716045025641, 4.041421509916807, -1.6349543418763945, + 7.9212454675679185, 0.7721147216829433, 8.959113895222348, + 4.982386370940765, 7.1514158587805365, 4.073127252924829, 3.973102469449036, + -1.4206098126378905, -2.884552512926147, 1.9047385965830614, + -3.169287508333552, -1.7392144968569563, 0.7721044520820948, + 1.927206272793925, 7.104641765501545, 3.4505110590561854, + 0.8733130174974519, 9.266268836620407, 0.08700274201436375, + 6.052240993895984, 0.9007896354342442, 6.173886287536836, 5.907638810176699, + 1.9606259324926214, -5.130693452152175, 3.0132523997110416, + 2.4628682686429966, 3.3604641188713784, 5.456330102509671, + 3.1129611127328216, 4.621919115236012, 1.6051966558753044, + -2.395592286301594, 9.415942637822253, 4.5551016138441645, + 5.462041681472252, 1.2553444252956512, 9.125289294805025, -5.19635425788795, + 0.6479316122636503, 9.211129276541376, 4.088576979982686, 1.778078098119498, + 8.272830237615167, 5.941247087817222, 6.483218672754511, 7.836505848839812, + 9.10777300419422, 0.8697894759196668, -1.8048153062968533, + 2.6932056631239343, 6.270438904360643, 3.793841292975147, 5.93176798393608, + 0.5794319523472153, -1.0634626786112789, 1.5525130634435254, + 1.9069750675731074, 5.450872922288456, 3.352999491608821, + 2.6061036797014023, 0.46996693176866594, 3.089799989155103, + 2.1768196533032103, 7.209632078897733, 2.9382709469704604, 5.81830042125279, + 3.0254259849920686, 7.952336979799083, 6.556182022826983, + -0.1976664554077333, 5.064374587699065, 2.5790684611219734, + 5.416054005071723, 7.929922860554962, -4.987485362225389, + -2.365232243588474, 6.067477778583785, 2.7165906101272084, + -5.0554658081074315, 4.826017906934126, 2.3051068664341603, + 3.2425676342002556, 1.2996408495052318, 0.703193985050713, + 2.7805627349610846, 1.0491896153647293, 6.821299225780244, + 0.7046460079936201, -2.953473023647294, -3.6590226625841997, + 0.4254855627307656, 4.5834436824020655, -0.1264574637622443, + 0.062170134272150034, 1.0044135902927296, 5.894066030179587, + -5.032302428711589, 4.3565237912861, 0.8204878684140501, 8.542998995034315, + 0.19522163995677777, -5.105510462957291, 3.664400379320447, + 9.523795502928193, 3.1412037401144466, 2.2838679019892427, + 8.175845575985958, 1.4812611753280103, 9.229352687073469, 7.315547660481734, + 5.826430520451797, 0.7545773335194408, -2.2423574079782207, + 6.472756705414401, 1.37941517062476, -2.1564940827513968, 3.372013235866089, + 2.3650725020331045, 6.568125635833751, 2.445340791793013, + -0.9932390025071863, 6.221281466545461, 7.995363198747193, + 3.5240304820715087, 3.7052514666884435, 3.039674786023824, 8.72316174744997, + 9.686001035805639, 8.472376648409222, 0.3369873707042546, + 0.4055299277861853, 9.055907499616207, -5.005667267446557, + 7.961191247169811, 3.229307450854857, 5.780672932325554, 6.190242116673266, + 6.102394102049797, 4.171372057552599, 1.241947275086106, + -2.0859279953693677, 9.473391633273852, 5.49488016127507, 9.122434389343034, + 1.0929961023746564, 6.043910303777906, 5.392428857667593, + 7.4885983371889955, 8.349677984222893, 9.566987967368911, 0.36722542845369793 ] ] diff --git a/client/__tests__/util/annoMatrix/whereCache.test.ts b/client/__tests__/util/annoMatrix/whereCache.test.js similarity index 64% rename from client/__tests__/util/annoMatrix/whereCache.test.ts rename to client/__tests__/util/annoMatrix/whereCache.test.js index 69eca458..e087399e 100644 --- a/client/__tests__/util/annoMatrix/whereCache.test.ts +++ b/client/__tests__/util/annoMatrix/whereCache.test.js @@ -4,34 +4,13 @@ import { _whereCacheCreate, _whereCacheMerge, } from "../../../src/annoMatrix/whereCache"; -import { Field, Schema } from "../../../src/common/types/schema"; -import { Query } from "../../../src/annoMatrix/query"; -const schema = {} as Schema; +const schema = {}; describe("whereCache", () => { test("whereCacheGet - where query, missing cache values", () => { expect( - _whereCacheGet({}, schema, Field.X, { - where: { - field: Field.var, - column: "foo", - value: "bar", - }, - }) - ).toEqual([undefined]); - expect( - _whereCacheGet({}, schema, Field.X, { - summarize: { - method: "mean", - field: Field.var, - column: "foo", - values: ["bar"], - }, - }) - ).toEqual([undefined]); - expect( - _whereCacheGet({ where: { X: {} } }, schema, Field.X, { + _whereCacheGet({}, schema, "X", { where: { field: "var", column: "foo", @@ -40,7 +19,25 @@ describe("whereCache", () => { }) ).toEqual([undefined]); expect( - _whereCacheGet({ where: { X: { var: new Map() } } }, schema, Field.X, { + _whereCacheGet({}, schema, "X", { + summarize: { + field: "var", + column: "foo", + values: ["bar"], + }, + }) + ).toEqual([undefined]); + expect( + _whereCacheGet({ where: { X: {} } }, schema, "X", { + where: { + field: "var", + column: "foo", + value: "bar", + }, + }) + ).toEqual([undefined]); + expect( + _whereCacheGet({ where: { X: { var: new Map() } } }, schema, "X", { where: { field: "var", column: "foo", @@ -52,7 +49,7 @@ describe("whereCache", () => { _whereCacheGet( { where: { X: { var: new Map([["foo", new Map()]]) } } }, schema, - Field.X, + "X", { where: { field: "var", @@ -66,7 +63,7 @@ describe("whereCache", () => { test("whereCacheGet - summarize query, missing cache values", () => { expect( - _whereCacheGet({}, schema, Field.X, { + _whereCacheGet({}, schema, "X", { summarize: { method: "mean", field: "var", @@ -79,7 +76,7 @@ describe("whereCache", () => { _whereCacheGet( { summarize: { X: { mean: { var: new Map() } } } }, schema, - Field.X, + "X", { summarize: { method: "mean", @@ -125,7 +122,7 @@ describe("whereCache", () => { }; expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { where: { field: "var", column: "foo", @@ -134,7 +131,7 @@ describe("whereCache", () => { }) ).toEqual([0]); expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { summarize: { method: "mean", field: "var", @@ -144,7 +141,7 @@ describe("whereCache", () => { }) ).toEqual([0]); expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { where: { field: "var", column: "foo", @@ -153,7 +150,7 @@ describe("whereCache", () => { }) ).toEqual([1, 2]); expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { summarize: { method: "mean", field: "var", @@ -162,12 +159,9 @@ describe("whereCache", () => { }, }) ).toEqual([1, 2]); + expect(_whereCacheGet(whereCache, schema, "Y", {})).toEqual([undefined]); expect( - // Force invalid field value Y - _whereCacheGet(whereCache, schema, "Y" as Field, {} as Query) - ).toEqual([undefined]); - expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { where: { field: "whoknows", column: "whatever", @@ -176,7 +170,7 @@ describe("whereCache", () => { }) ).toEqual([undefined]); expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { where: { field: "var", column: "whatever", @@ -185,7 +179,7 @@ describe("whereCache", () => { }) ).toEqual([undefined]); expect( - _whereCacheGet(whereCache, schema, Field.X, { + _whereCacheGet(whereCache, schema, "X", { where: { field: "var", column: "foo", @@ -204,7 +198,7 @@ describe("whereCache", () => { }, }; const wc = _whereCacheCreate( - Field.obs, + "field", { where: { field: "queryField", @@ -218,27 +212,18 @@ describe("whereCache", () => { expect(wc).toEqual( expect.objectContaining({ where: { - [Field.obs]: { + field: { queryField: expect.any(Map), }, }, }) ); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - expect((wc.where as any)[Field.obs].queryField.has("queryColumn")).toEqual(true); + expect(wc.where.field.queryField.has("queryColumn")).toEqual(true); + expect(wc.where.field.queryField.get("queryColumn")).toBeInstanceOf(Map); expect( - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (wc.where as any)[Field.obs].queryField.get("queryColumn") - ).toBeInstanceOf(Map); - expect( - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (wc.where as any)[Field.obs].queryField.get("queryColumn").has("queryValue") + wc.where.field.queryField.get("queryColumn").has("queryValue") ).toEqual(true); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null - expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]); + expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]); }); test("whereCacheCreate, summarize query", () => { @@ -250,14 +235,12 @@ describe("whereCache", () => { values: ["queryValue"], }, }; - const wc = _whereCacheCreate(Field.obs, query, [0, 1, 2]); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null - expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]); + const wc = _whereCacheCreate("field", query, [0, 1, 2]); + expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]); }); test("whereCacheCreate, unknown query type", () => { - // @ts-expect-error --- force invalid query {foobar: true} - expect(_whereCacheCreate(Field.obs, { foobar: true }, [1])).toEqual({}); + expect(_whereCacheCreate("field", { foobar: true }, [1])).toEqual({}); }); test("whereCacheMerge, where queries", () => { @@ -265,20 +248,19 @@ describe("whereCache", () => { // remember, will mutate dst const src = _whereCacheCreate( - Field.obs, + "field", { where: { field: "queryField", column: "queryColumn", value: "foo" } }, ["foo"] ); const dst1 = _whereCacheCreate( - Field.obs, + "field", { where: { field: "queryField", column: "queryColumn", value: "bar" } }, ["dst1"] ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst1 and src to be non-null - wc = _whereCacheMerge(dst1!, src!); + wc = _whereCacheMerge(dst1, src); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -287,7 +269,7 @@ describe("whereCache", () => { }) ).toEqual(["foo"]); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -297,14 +279,13 @@ describe("whereCache", () => { ).toEqual(["dst1"]); const dst2 = _whereCacheCreate( - Field.obs, + "field", { where: { field: "queryField", column: "queryColumn", value: "bar" } }, ["dst2"] ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst2m, dst1 and src to be non-null - wc = _whereCacheMerge(dst2!, dst1!, src!); + wc = _whereCacheMerge(dst2, dst1, src); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -313,7 +294,7 @@ describe("whereCache", () => { }) ).toEqual(["foo"]); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -322,20 +303,17 @@ describe("whereCache", () => { }) ).toEqual(["dst1"]); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null - wc = _whereCacheMerge({}, src!); + wc = _whereCacheMerge({}, src); expect(wc).toEqual(src); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null - wc = _whereCacheMerge({ where: { obs: { queryField: new Map() } } }, src!); + wc = _whereCacheMerge({ where: { field: { queryField: new Map() } } }, src); expect(wc).toEqual(src); }); test("whereCacheMerge, mixed queries", () => { const wc = _whereCacheMerge( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null _whereCacheCreate( - Field.obs, + "field", { where: { field: "queryField", @@ -344,10 +322,9 @@ describe("whereCache", () => { }, }, ["a"] - )!, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null + ), _whereCacheCreate( - Field.obs, + "field", { summarize: { method: "mean", @@ -357,11 +334,11 @@ describe("whereCache", () => { }, }, ["b"] - )! + ) ); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -371,7 +348,7 @@ describe("whereCache", () => { ).toEqual(["a"]); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { summarize: { method: "mean", field: "queryField", @@ -382,7 +359,7 @@ describe("whereCache", () => { ).toEqual(["b"]); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { where: { field: "queryField", column: "queryColumn", @@ -392,7 +369,7 @@ describe("whereCache", () => { ).toEqual([undefined]); expect( - _whereCacheGet(wc, schema, Field.obs, { + _whereCacheGet(wc, schema, "field", { summarize: { method: "no-such-method", field: "queryField", diff --git a/client/__tests__/util/centroid.test.ts b/client/__tests__/util/centroid.test.js similarity index 69% rename from client/__tests__/util/centroid.test.ts rename to client/__tests__/util/centroid.test.js index f9676a09..73eff556 100644 --- a/client/__tests__/util/centroid.test.ts +++ b/client/__tests__/util/centroid.test.js @@ -1,19 +1,16 @@ import cloneDeep from "lodash.clonedeep"; -import { NumberArray } from "../../src/common/types/arraytypes"; import calcCentroid from "../../src/util/centroid"; import quantile from "../../src/util/quantile"; import { matrixFBSToDataframe } from "../../src/util/stateManager/matrix"; import * as REST from "./stateManager/sampleResponses"; import { indexEntireSchema } from "../../src/util/stateManager/schemaHelpers"; import { normalizeWritableCategoricalSchema } from "../../src/annoMatrix/normalize"; -import { Dataframe } from "../../src/util/dataframe"; describe("centroid", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let schema: any; - let obsAnnotations: Dataframe; - let obsLayout: Dataframe; + let schema; + let obsAnnotations; + let obsLayout; beforeAll(() => { schema = indexEntireSchema(cloneDeep(REST.schema.schema)); @@ -43,12 +40,11 @@ describe("centroid", () => { // This expected result assumes that all cells belong in all categorical values inside of sample response const expectedResult = [ - quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0], - quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0], + quantile([0.5], obsLayout.col("umap_0").asArray())[0], + quantile([0.5], obsLayout.col("umap_1").asArray())[0], ]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - centroidResult.forEach((coordinate: any) => { + centroidResult.forEach((coordinate) => { expect(coordinate).toEqual(expectedResult); }); }); @@ -68,12 +64,11 @@ describe("centroid", () => { // This expected result assumes that all cells belong in all categorical values inside of sample response const expectedResult = [ - quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0], - quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0], + quantile([0.5], obsLayout.col("umap_0").asArray())[0], + quantile([0.5], obsLayout.col("umap_1").asArray())[0], ]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - centroidResult.forEach((coordinate: any) => { + centroidResult.forEach((coordinate) => { expect(coordinate).toEqual(expectedResult); }); }); diff --git a/client/__tests__/util/dataframe/dataframe.test.ts b/client/__tests__/util/dataframe/dataframe.test.js similarity index 82% rename from client/__tests__/util/dataframe/dataframe.test.ts rename to client/__tests__/util/dataframe/dataframe.test.js index d3d3872c..73e20e3e 100644 --- a/client/__tests__/util/dataframe/dataframe.test.ts +++ b/client/__tests__/util/dataframe/dataframe.test.js @@ -6,8 +6,7 @@ describe("dataframe constructor", () => { expect(df).toBeDefined(); expect(df.dims).toEqual([0, 0]); expect(df).toHaveLength(0); - expect(df.ihasCol(0)).toBeFalsy(); - expect(() => df.icol(0)).toThrow(RangeError); + expect(df.icol(0)).not.toBeDefined(); }); test("create with default indices", () => { @@ -24,13 +23,6 @@ describe("dataframe constructor", () => { expect(df.at(2, 1)).toEqual(1); expect(df.iat(0, 0)).toEqual(0); expect(df.iat(2, 1)).toEqual(1); - - expect(Array.from(df.rowIndex.labels())).toEqual( - df.rowIndex.getLabels(df.rowIndex.getOffsets(df.rowIndex.labels())) - ); - expect(Array.from(df.colIndex.labels())).toEqual( - df.colIndex.getLabels(df.colIndex.getOffsets(df.colIndex.labels())) - ); }); test("create with labelled indices", () => { @@ -129,9 +121,7 @@ describe("simple data access", () => { expect(df.has(3, "foo")).toBeFalsy(); expect(df.has(-1, "numbers")).toBeFalsy(); expect(df.has(-1, -1)).toBeFalsy(); - expect( - df.has(null as unknown as number, null as unknown as number) - ).toBeFalsy(); + expect(df.has(null, null)).toBeFalsy(); expect(df.has(0, "foo")).toBeFalsy(); expect(df.has(99, "numbers")).toBeFalsy(); expect(df.has(99, "foo")).toBeFalsy(); @@ -259,12 +249,11 @@ describe("dataframe subsetting", () => { const df = sourceDf.subset( null, ["int32", "float32"], - new Dataframe.DenseInt32Index([2, 1]) + new Dataframe.DenseInt32Index([3, 2, 1]) ); - expect(df.dims).toEqual([2, 2]); expect(df.colIndex).toBeInstanceOf(Dataframe.KeyIndex); expect(df.rowIndex).toBeInstanceOf(Dataframe.DenseInt32Index); - expect(df.at(2, "int32")).toEqual(df.iat(0, 0)); + expect(df.at(3, "int32")).toEqual(df.iat(0, 0)); }); test("withRowIndex error checks", () => { @@ -843,7 +832,7 @@ describe("dataframe factories", () => { }); describe("dataframe col", () => { - let df: Dataframe.Dataframe; + let df = null; beforeEach(() => { df = new Dataframe.Dataframe( [2, 2], @@ -860,8 +849,8 @@ describe("dataframe col", () => { expect(df).toBeDefined(); expect(df.col("A")).toBe(df.icol(0)); expect(df.col("B")).toBe(df.icol(1)); - expect(() => df.col("undefined")).toThrow(RangeError); - expect(() => df.icol("undefined" as unknown as number)).toThrow(RangeError); + expect(df.col("undefined")).toBeUndefined(); + expect(df.icol("undefined")).toBeUndefined(); const colA = df.col("A"); expect(colA).toBeInstanceOf(Function); @@ -915,13 +904,13 @@ describe("dataframe col", () => { expect(df.col("A").indexOf(true)).toEqual(0); expect(df.col("A").indexOf(false)).toEqual(1); expect(df.col("A").indexOf(99)).toBeUndefined(); - expect(df.col("A").indexOf(undefined as unknown as number)).toBeUndefined(); + expect(df.col("A").indexOf(undefined)).toBeUndefined(); expect(df.col("A").indexOf(1)).toBeUndefined(); expect(df.col("B").indexOf(1)).toEqual(0); expect(df.col("B").indexOf(0)).toEqual(1); expect(df.col("B").indexOf(99)).toBeUndefined(); - expect(df.col("B").indexOf(undefined as unknown as number)).toBeUndefined(); + expect(df.col("B").indexOf(undefined)).toBeUndefined(); expect(df.col("B").indexOf(true)).toBeUndefined(); }); }); @@ -964,7 +953,7 @@ describe("label indexing", () => { test("offsets", () => { expect(idx.getOffset(1)).toEqual(1); - expect(idx.getOffsets([1, 3])).toEqual(new Int32Array([1, 3])); + expect(idx.getOffsets([1, 3])).toEqual([1, 3]); }); test("subset", () => { @@ -1042,7 +1031,7 @@ describe("label indexing", () => { false, ]) .labels() - ).toEqual([]); + ).toEqual(new Int32Array([])); expect( idx .isubsetMask([ @@ -1136,14 +1125,16 @@ describe("label indexing", () => { expect(idx.labels()).toEqual(new Int32Array([99, 1002, 48, 0, 22])); expect(idx.size()).toEqual(5); expect(idx.getLabel(0)).toEqual(99); - expect(idx.getLabels(new Int32Array([2, 4]))).toEqual([48, 22]); + expect(idx.getLabels(new Int32Array([2, 4]))).toEqual( + new Int32Array([48, 22]) + ); expect(idx.getLabels([2, 4])).toEqual([48, 22]); }); test("offsets", () => { expect(idx.getOffset(1002)).toEqual(1); expect(idx.getOffset(0)).toEqual(3); - expect(idx.getOffsets([0, 48])).toEqual(new Int32Array([3, 2])); + expect(idx.getOffsets([0, 48])).toEqual([3, 2]); }); test("subset", () => { @@ -1170,7 +1161,7 @@ describe("label indexing", () => { ); expect( idx.isubsetMask([false, false, false, false, false]).labels() - ).toEqual([]); + ).toEqual(new Int32Array([])); expect(idx.isubsetMask([true, true, false, true, true]).labels()).toEqual( new Int32Array([99, 1002, 0, 22]) ); @@ -1202,7 +1193,6 @@ describe("label indexing", () => { test("create", () => { expect(Dataframe.isLabelIndex(idx)).toBeTruthy(); 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); }); @@ -1272,67 +1262,59 @@ describe("corner cases", () => { const idx = new Dataframe.IdentityInt32Index(10); expect(idx.getOffset(0)).toBe(0); expect(idx.getOffset(9)).toBe(9); - expect(idx.getOffset(10)).toBe(-1); - expect(idx.getOffset(-1)).toBe(-1); - expect(idx.getOffset("sort")).toBe(-1); - expect(idx.getOffset("length")).toBe(-1); - expect(idx.getOffset(true as unknown as string)).toBe(-1); - expect(idx.getOffset(0.001)).toBe(-1); - expect(idx.getOffset({} as unknown as string)).toBe(-1); - expect(idx.getOffset([] as unknown as string)).toBe(-1); - expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1); - expect(idx.getOffset("__proto__")).toBe(-1); + expect(idx.getOffset(10)).toBeUndefined(); + expect(idx.getOffset(-1)).toBeUndefined(); + expect(idx.getOffset("sort")).toBeUndefined(); + expect(idx.getOffset("length")).toBeUndefined(); + expect(idx.getOffset(true)).toBeUndefined(); + expect(idx.getOffset(0.001)).toBeUndefined(); + expect(idx.getOffset({})).toBeUndefined(); + expect(idx.getOffset([])).toBeUndefined(); + expect(idx.getOffset(new Float32Array())).toBeUndefined(); + expect(idx.getOffset("__proto__")).toBeUndefined(); expect(idx.getLabel(0)).toBe(0); expect(idx.getLabel(9)).toBe(9); expect(idx.getLabel(10)).toBeUndefined(); expect(idx.getLabel(-1)).toBeUndefined(); - expect(idx.getLabel("sort" as unknown as number)).toBeUndefined(); - expect(idx.getLabel("length" as unknown as number)).toBeUndefined(); - expect(idx.getLabel(true as unknown as number)).toBeUndefined(); + expect(idx.getLabel("sort")).toBeUndefined(); + expect(idx.getLabel("length")).toBeUndefined(); + expect(idx.getLabel(true)).toBeUndefined(); expect(idx.getLabel(0.001)).toBeUndefined(); - expect(idx.getLabel({} as unknown as number)).toBeUndefined(); - expect(idx.getLabel([] as unknown as number)).toBeUndefined(); - expect( - idx.getLabel(new Float32Array() as unknown as number) - ).toBeUndefined(); - expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined(); + expect(idx.getLabel({})).toBeUndefined(); + expect(idx.getLabel([])).toBeUndefined(); + expect(idx.getLabel(new Float32Array())).toBeUndefined(); + expect(idx.getLabel("__proto__")).toBeUndefined(); }); test("dense integer index rejects non-integer labels", () => { const idx = new Dataframe.DenseInt32Index([-10, 0, 3, 9, 10]); - expect(idx.getOffset(-10)).toBe(0); expect(idx.getOffset(0)).toBe(1); - expect(idx.getOffset(3)).toBe(2); expect(idx.getOffset(9)).toBe(3); - expect(idx.getOffset(10)).toBe(4); - - expect(idx.getOffset(1)).toBe(-1); - expect(idx.getOffset(11)).toBe(-1); - expect(idx.getOffset(-1)).toBe(-1); - expect(idx.getOffset("sort")).toBe(-1); - expect(idx.getOffset("length")).toBe(-1); - expect(idx.getOffset(true as unknown as string)).toBe(-1); - expect(idx.getOffset(0.001)).toBe(-1); - expect(idx.getOffset({} as unknown as string)).toBe(-1); - expect(idx.getOffset([] as unknown as string)).toBe(-1); - expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1); - expect(idx.getOffset("__proto__")).toBe(-1); + expect(idx.getOffset(1)).toBeUndefined(); + expect(idx.getOffset(11)).toBeUndefined(); + expect(idx.getOffset(-1)).toBeUndefined(); + expect(idx.getOffset("sort")).toBeUndefined(); + expect(idx.getOffset("length")).toBeUndefined(); + expect(idx.getOffset(true)).toBeUndefined(); + expect(idx.getOffset(0.001)).toBeUndefined(); + expect(idx.getOffset({})).toBeUndefined(); + expect(idx.getOffset([])).toBeUndefined(); + expect(idx.getOffset(new Float32Array())).toBeUndefined(); + expect(idx.getOffset("__proto__")).toBeUndefined(); expect(idx.getLabel(0)).toBe(-10); expect(idx.getLabel(4)).toBe(10); expect(idx.getLabel(10)).toBeUndefined(); expect(idx.getLabel(-1)).toBeUndefined(); - expect(idx.getLabel("sort" as unknown as number)).toBeUndefined(); - expect(idx.getLabel("length" as unknown as number)).toBeUndefined(); - expect(idx.getLabel(true as unknown as number)).toBeUndefined(); + expect(idx.getLabel("sort")).toBeUndefined(); + expect(idx.getLabel("length")).toBeUndefined(); + expect(idx.getLabel(true)).toBeUndefined(); expect(idx.getLabel(0.001)).toBeUndefined(); - expect(idx.getLabel({} as unknown as number)).toBeUndefined(); - expect(idx.getLabel([] as unknown as number)).toBeUndefined(); - expect( - idx.getLabel(new Float32Array() as unknown as number) - ).toBeUndefined(); - expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined(); + expect(idx.getLabel({})).toBeUndefined(); + expect(idx.getLabel([])).toBeUndefined(); + expect(idx.getLabel(new Float32Array())).toBeUndefined(); + expect(idx.getLabel("__proto__")).toBeUndefined(); }); test("Empty dataframe rejects bogus labels", () => { @@ -1340,55 +1322,39 @@ describe("corner cases", () => { expect(df.hasCol("sort")).toBeFalsy(); expect(df.hasCol(0)).toBeFalsy(); - expect(df.hasCol(true as unknown as number)).toBeFalsy(); - expect(df.hasCol(false as unknown as number)).toBeFalsy(); - expect(df.hasCol([] as unknown as number)).toBeFalsy(); - expect(df.hasCol({} as unknown as number)).toBeFalsy(); - expect(df.hasCol(null as unknown as number)).toBeFalsy(); - expect(df.hasCol(undefined as unknown as number)).toBeFalsy(); + expect(df.hasCol(true)).toBeFalsy(); + expect(df.hasCol(false)).toBeFalsy(); + expect(df.hasCol([])).toBeFalsy(); + expect(df.hasCol({})).toBeFalsy(); + expect(df.hasCol(null)).toBeFalsy(); + expect(df.hasCol(undefined)).toBeFalsy(); - expect(() => df.col("sort")).toThrow(RangeError); - expect(() => df.col(0)).toThrow(RangeError); - expect(() => df.col(true as unknown as string)).toThrow(RangeError); - expect(() => df.col(false as unknown as string)).toThrow(RangeError); - expect(() => df.col([] as unknown as string)).toThrow(RangeError); - expect(() => df.col({} as unknown as string)).toThrow(RangeError); - expect(() => df.col(null as unknown as string)).toThrow(RangeError); - expect(() => df.col(undefined as unknown as string)).toThrow(RangeError); + expect(df.col("sort")).toBeUndefined(); + expect(df.col(0)).toBeUndefined(); + expect(df.col(true)).toBeUndefined(); + expect(df.col(false)).toBeUndefined(); + expect(df.col([])).toBeUndefined(); + expect(df.col({})).toBeUndefined(); + expect(df.col(null)).toBeUndefined(); + expect(df.col(undefined)).toBeUndefined(); - expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError); - expect(() => df.icol(0)).toThrow(RangeError); - expect(() => df.icol(true as unknown as number)).toThrow(RangeError); - expect(() => df.icol(false as unknown as number)).toThrow(RangeError); - expect(() => df.icol([] as unknown as number)).toThrow(RangeError); - expect(() => df.icol({} as unknown as number)).toThrow(RangeError); - expect(() => df.icol(null as unknown as number)).toThrow(RangeError); - expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError); + expect(df.icol("sort")).toBeUndefined(); + expect(df.icol(0)).toBeUndefined(); + expect(df.icol(true)).toBeUndefined(); + expect(df.icol(false)).toBeUndefined(); + expect(df.icol([])).toBeUndefined(); + expect(df.icol({})).toBeUndefined(); + expect(df.icol(null)).toBeUndefined(); + expect(df.icol(undefined)).toBeUndefined(); - expect( - df.ihas("sort" as unknown as number, "length" as unknown as number) - ).toBeFalsy(); - expect( - df.ihas("0" as unknown as number, "0" as unknown as number) - ).toBeFalsy(); - expect( - df.ihas("" as unknown as number, "" as unknown as number) - ).toBeFalsy(); - expect( - df.ihas(null as unknown as number, null as unknown as number) - ).toBeFalsy(); - expect( - df.ihas(undefined as unknown as number, undefined as unknown as number) - ).toBeFalsy(); - expect( - df.ihas(true as unknown as number, true as unknown as number) - ).toBeFalsy(); - expect( - df.ihas([] as unknown as number, [] as unknown as number) - ).toBeFalsy(); - expect( - df.ihas({} as unknown as number, {} as unknown as number) - ).toBeFalsy(); + expect(df.ihas("sort", "length")).toBeFalsy(); + expect(df.ihas("0", "0")).toBeFalsy(); + expect(df.ihas("", "")).toBeFalsy(); + expect(df.ihas(null, null)).toBeFalsy(); + expect(df.ihas(undefined, undefined)).toBeFalsy(); + expect(df.ihas(true, true)).toBeFalsy(); + expect(df.ihas([], [])).toBeFalsy(); + expect(df.ihas({}, {})).toBeFalsy(); }); test("Dataframe rejects bogus labels", () => { @@ -1405,58 +1371,51 @@ describe("corner cases", () => { expect(df.hasCol("sort")).toBeFalsy(); expect(df.hasCol("__proto__")).toBeFalsy(); expect(df.hasCol(0)).toBeFalsy(); - expect(df.hasCol(true as unknown as string)).toBeFalsy(); - expect(df.hasCol(false as unknown as string)).toBeFalsy(); - expect(df.hasCol([] as unknown as string)).toBeFalsy(); - expect(df.hasCol({} as unknown as string)).toBeFalsy(); - expect(df.hasCol(null as unknown as string)).toBeFalsy(); - expect(df.hasCol(undefined as unknown as string)).toBeFalsy(); + expect(df.hasCol(true)).toBeFalsy(); + expect(df.hasCol(false)).toBeFalsy(); + expect(df.hasCol([])).toBeFalsy(); + expect(df.hasCol({})).toBeFalsy(); + expect(df.hasCol(null)).toBeFalsy(); + expect(df.hasCol(undefined)).toBeFalsy(); - expect(() => df.col("sort")).toThrow(RangeError); - expect(() => df.col("__proto__")).toThrow(RangeError); - expect(() => df.col(0)).toThrow(RangeError); - expect(() => df.col(true as unknown as string)).toThrow(RangeError); - expect(() => df.col(false as unknown as string)).toThrow(RangeError); - expect(() => df.col([] as unknown as string)).toThrow(RangeError); - expect(() => df.col({} as unknown as string)).toThrow(RangeError); - expect(() => df.col(null as unknown as string)).toThrow(RangeError); - expect(() => df.col(undefined as unknown as string)).toThrow(RangeError); + expect(df.col("sort")).toBeUndefined(); + expect(df.col("__proto__")).toBeUndefined(); + expect(df.col(0)).toBeUndefined(); + expect(df.col(true)).toBeUndefined(); + expect(df.col(false)).toBeUndefined(); + expect(df.col([])).toBeUndefined(); + expect(df.col({})).toBeUndefined(); + expect(df.col(null)).toBeUndefined(); + expect(df.col(undefined)).toBeUndefined(); - expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError); - expect(() => df.icol("__proto__" as unknown as number)).toThrow(RangeError); - expect(() => df.icol(-1)).toThrow(RangeError); - expect(() => df.icol(true as unknown as number)).toThrow(RangeError); - expect(() => df.icol(false as unknown as number)).toThrow(RangeError); - expect(() => df.icol([] as unknown as number)).toThrow(RangeError); - expect(() => df.icol({} as unknown as number)).toThrow(RangeError); - expect(() => df.icol(null as unknown as number)).toThrow(RangeError); - expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError); + expect(df.icol("sort")).toBeUndefined(); + expect(df.icol("__proto__")).toBeUndefined(); + expect(df.icol(-1)).toBeUndefined(); + expect(df.icol(true)).toBeUndefined(); + expect(df.icol(false)).toBeUndefined(); + expect(df.icol([])).toBeUndefined(); + expect(df.icol({})).toBeUndefined(); + expect(df.icol(null)).toBeUndefined(); + expect(df.icol(undefined)).toBeUndefined(); - expect( - df.ihas("sort" as unknown as number, "length" as unknown as number) - ).toBeFalsy(); - expect( - df.ihas( - "__proto__" as unknown as number, - "__proto__" as unknown as number - ) - ).toBeFalsy(); + expect(df.ihas("sort", "length")).toBeFalsy(); + expect(df.ihas("__proto__", "__proto__")).toBeFalsy(); expect(df.ihas(-1, 0)).toBeFalsy(); - expect(df.ihas("0" as unknown as number, 0)).toBeFalsy(); - expect(df.ihas("" as unknown as number, 0)).toBeFalsy(); - expect(df.ihas(null as unknown as number, 0)).toBeFalsy(); - expect(df.ihas(undefined as unknown as number, 0)).toBeFalsy(); - expect(df.ihas([] as unknown as number, 0)).toBeFalsy(); - expect(df.ihas({} as unknown as number, 0)).toBeFalsy(); + expect(df.ihas("0", 0)).toBeFalsy(); + expect(df.ihas("", 0)).toBeFalsy(); + expect(df.ihas(null, 0)).toBeFalsy(); + expect(df.ihas(undefined, 0)).toBeFalsy(); + expect(df.ihas([], 0)).toBeFalsy(); + expect(df.ihas({}, 0)).toBeFalsy(); expect(df.ihas(0, -1)).toBeFalsy(); - expect(df.ihas(0, "0" as unknown as number)).toBeFalsy(); - expect(df.ihas(0, "" as unknown as number)).toBeFalsy(); - expect(df.ihas(0, null as unknown as number)).toBeFalsy(); - expect(df.ihas(0, undefined as unknown as number)).toBeFalsy(); - expect(df.ihas(0, [] as unknown as number)).toBeFalsy(); - expect(df.ihas(0, {} as unknown as number)).toBeFalsy(); + expect(df.ihas(0, "0")).toBeFalsy(); + expect(df.ihas(0, "")).toBeFalsy(); + expect(df.ihas(0, null)).toBeFalsy(); + expect(df.ihas(0, undefined)).toBeFalsy(); + expect(df.ihas(0, [])).toBeFalsy(); + expect(df.ihas(0, {})).toBeFalsy(); expect(df.has("sort", "length")).toBeFalsy(); expect(df.has("length", "sort")).toBeFalsy(); @@ -1465,17 +1424,17 @@ describe("corner cases", () => { expect(df.has(-1, "A")).toBeFalsy(); expect(df.has("0", "A")).toBeFalsy(); expect(df.has("", "A")).toBeFalsy(); - expect(df.has(null as unknown as string, "A")).toBeFalsy(); - expect(df.has(undefined as unknown as string, "A")).toBeFalsy(); - expect(df.has([] as unknown as string, "A")).toBeFalsy(); - expect(df.has({} as unknown as string, "A")).toBeFalsy(); + expect(df.has(null, "A")).toBeFalsy(); + expect(df.has(undefined, "A")).toBeFalsy(); + expect(df.has([], "A")).toBeFalsy(); + expect(df.has({}, "A")).toBeFalsy(); expect(df.has(0, -1)).toBeFalsy(); expect(df.has(0, "0")).toBeFalsy(); expect(df.has(0, "")).toBeFalsy(); - expect(df.has(0, null as unknown as string)).toBeFalsy(); - expect(df.has(0, undefined as unknown as string)).toBeFalsy(); - expect(df.has(0, [] as unknown as string)).toBeFalsy(); - expect(df.has(0, {} as unknown as string)).toBeFalsy(); + expect(df.has(0, null)).toBeFalsy(); + expect(df.has(0, undefined)).toBeFalsy(); + expect(df.has(0, [])).toBeFalsy(); + expect(df.has(0, {})).toBeFalsy(); }); }); diff --git a/client/__tests__/util/dataframe/histogram.test.ts b/client/__tests__/util/dataframe/histogram.test.js similarity index 69% rename from client/__tests__/util/dataframe/histogram.test.ts rename to client/__tests__/util/dataframe/histogram.test.js index c6a8c1a1..fb4fefa9 100644 --- a/client/__tests__/util/dataframe/histogram.test.ts +++ b/client/__tests__/util/dataframe/histogram.test.js @@ -9,7 +9,7 @@ describe("Dataframe column histogram", () => { new Dataframe.KeyIndex(["name", "cat", "value"]) ); - const h1 = df.col("cat").histogramCategoricalBy(df.col("name")); + const h1 = df.col("cat").histogram(df.col("name")); expect(h1).toMatchObject( new Map([ ["n1", new Map([["c1", 1]])], @@ -18,9 +18,7 @@ describe("Dataframe column histogram", () => { ]) ); // memoized? - expect(df.col("cat").histogramCategoricalBy(df.col("name"))).toMatchObject( - h1 - ); + expect(df.col("cat").histogram(df.col("name"))).toMatchObject(h1); }); test("continuous by categorical", () => { @@ -31,7 +29,7 @@ describe("Dataframe column histogram", () => { new Dataframe.KeyIndex(["name", "cat", "value"]) ); - const h1 = df.col("value").histogramContinuousBy(3, [0, 2], df.col("name")); + const h1 = df.col("value").histogram(3, [0, 2], df.col("name")); expect(h1).toMatchObject( new Map([ ["n1", [1, 0, 0]], @@ -40,9 +38,9 @@ describe("Dataframe column histogram", () => { ]) ); // memoized? - expect( - df.col("value").histogramContinuousBy(3, [0, 2], df.col("name")) - ).toMatchObject(h1); + expect(df.col("value").histogram(3, [0, 2], df.col("name"))).toMatchObject( + h1 + ); }); test("categorical", () => { @@ -53,7 +51,7 @@ describe("Dataframe column histogram", () => { new Dataframe.KeyIndex(["name", "cat", "value"]) ); - const h1 = df.col("cat").histogramCategorical(); + const h1 = df.col("cat").histogram(); expect(h1).toMatchObject( new Map([ ["c1", 1], @@ -62,7 +60,7 @@ describe("Dataframe column histogram", () => { ]) ); // memoized? - expect(df.col("cat").histogramCategorical()).toMatchObject(h1); + expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1); }); test("continuous", () => { @@ -73,10 +71,10 @@ describe("Dataframe column histogram", () => { new Dataframe.KeyIndex(["name", "cat", "value"]) ); - const h1 = df.col("value").histogramContinuous(3, [0, 2]); + const h1 = df.col("value").histogram(3, [0, 2]); expect(h1).toMatchObject([1, 1, 1]); // memoized? - expect(df.col("value").histogramContinuous(3, [0, 2])).toMatchObject(h1); + expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1); }); test("continuous thesholds correct", () => { @@ -86,10 +84,10 @@ describe("Dataframe column histogram", () => { [new Int32Array(vals), new Float32Array(vals)] ); - expect(df.col(0).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]); - expect(df.col(1).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]); - expect(df.col(0).histogramContinuous(2, [0, 10])).toEqual([2, 2]); - expect(df.col(0).histogramContinuous(10, [0, 100])).toEqual([ + expect(df.col(0).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]); + expect(df.col(1).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]); + expect(df.col(0).histogram(2, [0, 10])).toEqual([2, 2]); + expect(df.col(0).histogram(10, [0, 100])).toEqual([ 3, 2, 1, 0, 0, 0, 0, 0, 0, 2, ]); }); diff --git a/client/__tests__/util/dataframe/summarize.test.ts b/client/__tests__/util/dataframe/summarize.test.js similarity index 81% rename from client/__tests__/util/dataframe/summarize.test.ts rename to client/__tests__/util/dataframe/summarize.test.js index c2c421f2..ec98d7be 100644 --- a/client/__tests__/util/dataframe/summarize.test.ts +++ b/client/__tests__/util/dataframe/summarize.test.js @@ -1,14 +1,13 @@ import * as Dataframe from "../../../src/util/dataframe"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function float32Conversion(f: any) { +function float32Conversion(f) { return new Float32Array([f])[0]; } describe("Dataframe column summary", () => { test("empty column test", () => { const df = Dataframe.Dataframe.create([0, 1], [[]]); - const summary = df.icol(0).summarizeCategorical(); + const summary = df.icol(0).summarize(); expect(summary).toEqual( expect.objectContaining({ categorical: true, @@ -41,7 +40,7 @@ describe("Dataframe column summary", () => { ]) ); - expect(df.icol(0).summarizeCategorical()).toEqual( + expect(df.icol(0).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: ["n1"], @@ -49,7 +48,7 @@ describe("Dataframe column summary", () => { numCategories: 1, }) ); - expect(df.icol(1).summarizeCategorical()).toEqual( + expect(df.icol(1).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: ["hi"], @@ -57,7 +56,7 @@ describe("Dataframe column summary", () => { numCategories: 1, }) ); - expect(df.icol(2).summarizeCategorical()).toEqual( + expect(df.icol(2).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: [true], @@ -65,7 +64,7 @@ describe("Dataframe column summary", () => { numCategories: 1, }) ); - expect(df.icol(3).summarizeContinuous()).toEqual( + expect(df.icol(3).summarize()).toEqual( expect.objectContaining({ categorical: false, min: float32Conversion(39.3), @@ -75,7 +74,7 @@ describe("Dataframe column summary", () => { pinf: 0, }) ); - expect(df.icol(4).summarizeContinuous()).toEqual( + expect(df.icol(4).summarize()).toEqual( expect.objectContaining({ categorical: false, min: 99, @@ -85,7 +84,7 @@ describe("Dataframe column summary", () => { pinf: 0, }) ); - expect(df.icol(5).summarizeCategorical()).toEqual( + expect(df.icol(5).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: [1], @@ -117,7 +116,7 @@ describe("Dataframe column summary", () => { ]) ); - expect(df.icol(0).summarizeCategorical()).toEqual( + expect(df.icol(0).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining(["n0", "n1", "n2"]), @@ -129,7 +128,7 @@ describe("Dataframe column summary", () => { numCategories: 3, }) ); - expect(df.icol(1).summarizeCategorical()).toEqual( + expect(df.icol(1).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining(["hi", "bye"]), @@ -140,7 +139,7 @@ describe("Dataframe column summary", () => { numCategories: 2, }) ); - expect(df.icol(2).summarizeCategorical()).toEqual( + expect(df.icol(2).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining([true, false]), @@ -151,7 +150,7 @@ describe("Dataframe column summary", () => { numCategories: 2, }) ); - expect(df.icol(3).summarizeContinuous()).toEqual( + expect(df.icol(3).summarize()).toEqual( expect.objectContaining({ categorical: false, min: 0, @@ -161,7 +160,7 @@ describe("Dataframe column summary", () => { pinf: 0, }) ); - expect(df.icol(4).summarizeContinuous()).toEqual( + expect(df.icol(4).summarize()).toEqual( expect.objectContaining({ categorical: false, min: 99, @@ -171,11 +170,10 @@ describe("Dataframe column summary", () => { pinf: 0, }) ); - expect(df.icol(5).summarizeCategorical()).toEqual( + expect(df.icol(5).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining([1, false, "0"]), - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. categoryCounts: new Map([ [1, 1], [false, 1], @@ -213,7 +211,7 @@ describe("Dataframe column summary", () => { ]) ); - expect(df.icol(0).summarizeCategorical()).toEqual( + expect(df.icol(0).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining(["n0", "n1", "n2"]), @@ -225,7 +223,7 @@ describe("Dataframe column summary", () => { numCategories: 3, }) ); - expect(df.icol(1).summarizeCategorical()).toEqual( + expect(df.icol(1).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining(["hi", "bye"]), @@ -236,7 +234,7 @@ describe("Dataframe column summary", () => { numCategories: 2, }) ); - expect(df.icol(2).summarizeCategorical()).toEqual( + expect(df.icol(2).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining([true, false]), @@ -247,7 +245,7 @@ describe("Dataframe column summary", () => { numCategories: 2, }) ); - expect(df.icol(3).summarizeContinuous()).toEqual( + expect(df.icol(3).summarize()).toEqual( expect.objectContaining({ categorical: false, min: float32Conversion(39.3), @@ -257,7 +255,7 @@ describe("Dataframe column summary", () => { pinf: 1, }) ); - expect(df.icol(4).summarizeContinuous()).toEqual( + expect(df.icol(4).summarize()).toEqual( expect.objectContaining({ categorical: false, min: 99, @@ -267,11 +265,10 @@ describe("Dataframe column summary", () => { pinf: 0, }) ); - expect(df.icol(5).summarizeCategorical()).toEqual( + expect(df.icol(5).summarize()).toEqual( expect.objectContaining({ categorical: true, categories: expect.arrayContaining([1, false, "0"]), - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. categoryCounts: new Map([ [1, 1], [false, 1], diff --git a/client/__tests__/util/nameCreators.test.ts b/client/__tests__/util/nameCreators.test.js similarity index 100% rename from client/__tests__/util/nameCreators.test.ts rename to client/__tests__/util/nameCreators.test.js diff --git a/client/__tests__/util/promiseLimit.test.ts b/client/__tests__/util/promiseLimit.test.js similarity index 91% rename from client/__tests__/util/promiseLimit.test.ts rename to client/__tests__/util/promiseLimit.test.js index 6b51ff0c..b22ff5b1 100644 --- a/client/__tests__/util/promiseLimit.test.ts +++ b/client/__tests__/util/promiseLimit.test.js @@ -1,8 +1,7 @@ import PromiseLimit from "../../src/util/promiseLimit"; import { range } from "../../src/util/range"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const delay = (t: any) => new Promise((resolve) => setTimeout(resolve, t)); +const delay = (t) => new Promise((resolve) => setTimeout(resolve, t)); describe("PromiseLimit", () => { test("simple evaluation, concurrency 1", async () => { @@ -52,7 +51,7 @@ describe("PromiseLimit", () => { running -= 1; }; - await Promise.all(range(10).map(() => plimit.add(() => callback()))); + await Promise.all(range(10).map((i) => plimit.add(() => callback(i)))); expect(maxRunning).toEqual(2); }); diff --git a/client/__tests__/util/quantile.test.ts b/client/__tests__/util/quantile.test.js similarity index 95% rename from client/__tests__/util/quantile.test.ts rename to client/__tests__/util/quantile.test.js index b316554c..88cf23c7 100644 --- a/client/__tests__/util/quantile.test.ts +++ b/client/__tests__/util/quantile.test.js @@ -19,11 +19,7 @@ describe("quantile", () => { test("multi q", () => { const arr = new Float32Array([9, 3, 5, 6, 0]); expect(quantile([0, 0.25, 0.5, 0.75, 1.0], arr)).toMatchObject([ - 0, - 3, - 5, - 6, - 9, + 0, 3, 5, 6, 9, ]); }); }); diff --git a/client/__tests__/util/range.test.ts b/client/__tests__/util/range.test.js similarity index 100% rename from client/__tests__/util/range.test.ts rename to client/__tests__/util/range.test.js diff --git a/client/__tests__/util/stateManager/colorHelpers.test.ts b/client/__tests__/util/stateManager/colorHelpers.test.js similarity index 71% rename from client/__tests__/util/stateManager/colorHelpers.test.ts rename to client/__tests__/util/stateManager/colorHelpers.test.js index 6ab9a0de..5ac9973c 100644 --- a/client/__tests__/util/stateManager/colorHelpers.test.ts +++ b/client/__tests__/util/stateManager/colorHelpers.test.js @@ -95,7 +95,6 @@ describe("categorical color helpers", () => { const data = obsDataframe.col("categoricalColumn").asArray(); const cats = schema.annotations.obsByName.categoricalColumn.categories; 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]))); } }); @@ -113,7 +112,6 @@ describe("categorical color helpers", () => { const data = obsDataframe.col("categoricalColumn").asArray(); const cats = schemaClone.annotations.obsByName.categoricalColumn.categories; 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]))); } }); @@ -124,8 +122,7 @@ describe("categorical color helpers", () => { Array.from(schema.annotations.obsByName.categoricalColumn.categories) ); const userDefinedColorTable = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoricalColumn: shuffleCats.reduce((acc: any, label: any) => { + categoricalColumn: shuffleCats.reduce((acc, label) => { acc[label] = randRGBColor(); return acc; }, {}), @@ -139,14 +136,12 @@ describe("categorical color helpers", () => { "categoricalColumn", obsDataframe, 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 ); expect(ct).toBeDefined(); const data = obsDataframe.col("categoricalColumn").asArray(); for (let i = 0; i < schema.dataframe.nObs; i += 1) { 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() ); } @@ -159,38 +154,31 @@ TODO: 2. user defined colors */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function indexSchema(schema: any) { +function indexSchema(schema) { schema.annotations.obsByName = Object.fromEntries( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema.annotations?.obs?.columns?.map((v: any) => [v.name, v]) ?? [] + schema.annotations?.obs?.columns?.map((v) => [v.name, v]) ?? [] ); schema.annotations.varByName = Object.fromEntries( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema.annotations?.var?.columns?.map((v: any) => [v.name, v]) ?? [] + schema.annotations?.var?.columns?.map((v) => [v.name, v]) ?? [] ); schema.layout.obsByName = Object.fromEntries( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema.layout?.obs?.map((v: any) => [v.name, v]) ?? [] + schema.layout?.obs?.map((v) => [v.name, v]) ?? [] ); schema.layout.varByName = Object.fromEntries( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema.layout?.var?.map((v: any) => [v.name, v]) ?? [] + schema.layout?.var?.map((v) => [v.name, v]) ?? [] ); return schema; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function makeScale(rgb: any) { +function makeScale(rgb) { // make a scale string from a rgb float triple return `rgb(${(rgb[0] * 255) >>> 0}, ${(rgb[1] * 255) >>> 0}, ${ (rgb[2] * 256) >>> 0 })`; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function shuffle(array: any) { +function shuffle(array) { for (let i = array.length - 1; i > 0; i -= 1) { const j = (Math.random() * (i + 1)) >>> 0; [array[i], array[j]] = [array[j], array[i]]; diff --git a/client/__tests__/util/stateManager/controlsHelpers.test.ts b/client/__tests__/util/stateManager/controlsHelpers.test.js similarity index 100% rename from client/__tests__/util/stateManager/controlsHelpers.test.ts rename to client/__tests__/util/stateManager/controlsHelpers.test.js diff --git a/client/__tests__/util/stateManager/fbs.test.ts b/client/__tests__/util/stateManager/fbs.test.js similarity index 100% rename from client/__tests__/util/stateManager/fbs.test.ts rename to client/__tests__/util/stateManager/fbs.test.js diff --git a/client/__tests__/util/stateManager/sampleResponses.ts b/client/__tests__/util/stateManager/sampleResponses.js similarity index 73% rename from client/__tests__/util/stateManager/sampleResponses.ts rename to client/__tests__/util/stateManager/sampleResponses.js index f5ef9254..7c54635a 100644 --- a/client/__tests__/util/stateManager/sampleResponses.ts +++ b/client/__tests__/util/stateManager/sampleResponses.js @@ -5,7 +5,6 @@ import zip from "lodash.zip"; import _ from "lodash"; import { flatbuffers } from "flatbuffers"; import { NetEncoding } from "../../../src/util/stateManager/matrix_generated"; -import { RawSchema } from "../../../src/common/types/schema"; /* test data mocking REST 0.2 API responses. Used in several tests. @@ -30,7 +29,7 @@ const aConfigResponse = { }, }; -const aSchemaResponse: { schema: RawSchema } = { +const aSchemaResponse = { schema: { dataframe: { nObs, @@ -41,30 +40,28 @@ const aSchemaResponse: { schema: RawSchema } = { obs: { index: "name", columns: [ - { name: "name", type: "string", writable: false }, - { name: "field1", type: "int32", writable: false }, - { name: "field2", type: "float32", writable: false }, - { name: "field3", type: "boolean", writable: false }, + { name: "name", type: "string" }, + { name: "field1", type: "int32" }, + { name: "field2", type: "float32" }, + { name: "field3", type: "boolean" }, { name: "field4", type: "categorical", categories: field4Categories, - writable: false, }, ], }, var: { index: "name", columns: [ - { name: "name", type: "string", writable: false }, - { name: "fieldA", type: "int32", writable: false }, - { name: "fieldB", type: "float32", writable: false }, - { name: "fieldC", type: "boolean", writable: false }, + { name: "name", type: "string" }, + { name: "fieldA", type: "int32" }, + { name: "fieldB", type: "float32" }, + { name: "fieldC", type: "boolean" }, { name: "fieldD", type: "categorical", categories: fieldDCategories, - writable: false, }, ], }, @@ -78,7 +75,6 @@ const aSchemaResponse: { schema: RawSchema } = { const anAnnotationsObsJSONResponse = { names: ["name", "field1", "field2", "field3", "field4"], - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. data: _() .range(nObs) .map((idx) => [ @@ -95,7 +91,6 @@ const anAnnotationsObsJSONResponse = { const anAnnotationsVarJSONResponse = { names: ["fieldA", "fieldB", "fieldC", "fieldD", "name"], - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. data: _() .range(nVar) .map((idx) => [ @@ -110,11 +105,8 @@ const anAnnotationsVarJSONResponse = { .value(), }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function encodeTypedArray(builder: any, uType: any, uData: any) { - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. +function encodeTypedArray(builder, uType, uData) { const uTypeName = NetEncoding.TypedArray[uType]; - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. const ArrayType = NetEncoding[uTypeName]; const dv = ArrayType.createDataVector(builder, uData); builder.startObject(1); @@ -122,8 +114,7 @@ function encodeTypedArray(builder: any, uType: any, uData: any) { return builder.endObject(); } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function encodeMatrix(columns: any, colIndex = undefined) { +function encodeMatrix(columns, colIndex = undefined) { /* IMPORTANT: this is not a general purpose encoder. in particular, it doesn't correctly handle all column index types, nor does it @@ -132,7 +123,6 @@ function encodeMatrix(columns: any, colIndex = undefined) { encodeMatrixFBS in matrix.py is more general. This is used only 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 builder = new flatbuffers.Builder(1024); const cols = map(columns, (carr) => { @@ -182,13 +172,11 @@ function encodeMatrix(columns: any, colIndex = undefined) { const anAnnotationsObsFBSResponse = (() => { 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); })(); const anAnnotationsVarFBSResponse = (() => { 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); })(); @@ -197,13 +185,11 @@ const aLayoutFBSResponse = (() => { 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"]); })(); const aDataObsResponse = { var: [2, 4, 29], - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. obs: _() .range(nObs) .map((idx) => [idx, Math.random(), Math.random(), Math.random()]) diff --git a/client/__tests__/util/typedCrossfilter/bitArray.test.ts b/client/__tests__/util/typedCrossfilter/bitArray.test.js similarity index 100% rename from client/__tests__/util/typedCrossfilter/bitArray.test.ts rename to client/__tests__/util/typedCrossfilter/bitArray.test.js diff --git a/client/__tests__/util/typedCrossfilter/crossfilter.test.ts b/client/__tests__/util/typedCrossfilter/crossfilter.test.js similarity index 79% rename from client/__tests__/util/typedCrossfilter/crossfilter.test.ts rename to client/__tests__/util/typedCrossfilter/crossfilter.test.js index fc6e18bf..58fa60bb 100644 --- a/client/__tests__/util/typedCrossfilter/crossfilter.test.ts +++ b/client/__tests__/util/typedCrossfilter/crossfilter.test.js @@ -126,8 +126,7 @@ const someData = [ }, ]; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -let payments: any = null; +let payments = null; beforeEach(() => { payments = new Crossfilter(someData); }); @@ -139,13 +138,7 @@ describe("ImmutableTypedCrossfilter", () => { expect(payments.all()).toEqual(someData); const p = payments - .addDimension( - "quantity", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].quantity, - Int32Array - ) + .addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .select("quantity", { mode: "all" }); expect(p).toBeDefined(); expect(p.all()).toEqual(someData); @@ -165,8 +158,7 @@ describe("ImmutableTypedCrossfilter", () => { const p2 = payments.addDimension( "quantity", "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, data: any) => data[i].quantity, + (i, data) => data[i].quantity, Int32Array ); @@ -183,22 +175,10 @@ describe("ImmutableTypedCrossfilter", () => { test("select all and none", () => { let p = payments - .addDimension( - "quantity", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].quantity, - Int32Array - ) // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .addDimension("tip", "scalar", (i: any, d: any) => d[i].tip, Float32Array) - .addDimension( - "total", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].total, - Float32Array - ) // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .addDimension("type", "enum", (i: any, d: any) => d[i].type); + .addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) + .addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array) + .addDimension("total", "scalar", (i, d) => d[i].total, Float32Array) + .addDimension("type", "enum", (i, d) => d[i].type); expect(p).toBeDefined(); /* expect all records to be selected - default init state */ @@ -250,24 +230,11 @@ describe("ImmutableTypedCrossfilter", () => { }); describe("scalar dimension", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let p: any; + let p; beforeEach(() => { p = payments - .addDimension( - "quantity", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].quantity, - Int32Array - ) - .addDimension( - "tip", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].tip, - Float32Array - ) + .addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) + .addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array) .select("tip", { mode: "all" }); }); @@ -310,11 +277,9 @@ describe("ImmutableTypedCrossfilter", () => { }); describe("enum dimension", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let p: any; + let p; beforeEach(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - p = payments.addDimension("type", "enum", (i: any, d: any) => d[i].type); + p = payments.addDimension("type", "enum", (i, d) => d[i].type); }); test("all", () => { @@ -352,8 +317,7 @@ describe("ImmutableTypedCrossfilter", () => { }); describe("spatial dimension", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let p: any; + let p; beforeEach(() => { const X = someData.map((r) => r.coords[0]); const Y = someData.map((r) => r.coords[1]); @@ -442,22 +406,14 @@ describe("ImmutableTypedCrossfilter", () => { }); describe("non-finite scalars", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let p: any; + let p; beforeEach(() => { p = payments - .addDimension( - "quantity", - "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].quantity, - Int32Array - ) + .addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array) .addDimension( "nonFinite", "scalar", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any, d: any) => d[i].nonFinite, + (i, d) => d[i].nonFinite, Float32Array ) .select("quantity", { mode: "all" }); diff --git a/client/__tests__/util/typedCrossfilter/positiveInterval.test.ts b/client/__tests__/util/typedCrossfilter/positiveInterval.test.js similarity index 97% rename from client/__tests__/util/typedCrossfilter/positiveInterval.test.ts rename to client/__tests__/util/typedCrossfilter/positiveInterval.test.js index 7c43e8a5..58d45095 100644 --- a/client/__tests__/util/typedCrossfilter/positiveInterval.test.ts +++ b/client/__tests__/util/typedCrossfilter/positiveInterval.test.js @@ -151,9 +151,9 @@ describe("intersection", () => { [1, 2], [6, 9], ]); - expect( - PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]]) - ).toEqual([[1363, 2638]]); + expect(PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]])).toEqual( + [[1363, 2638]] + ); expect(PositiveIntervals.intersection([[1, 2]], [[1, 2]])).toEqual([ [1, 2], ]); diff --git a/client/__tests__/util/typedCrossfilter/sort.test.ts b/client/__tests__/util/typedCrossfilter/sort.test.js similarity index 84% rename from client/__tests__/util/typedCrossfilter/sort.test.ts rename to client/__tests__/util/typedCrossfilter/sort.test.js index 21d1affd..f7650f4f 100644 --- a/client/__tests__/util/typedCrossfilter/sort.test.ts +++ b/client/__tests__/util/typedCrossfilter/sort.test.js @@ -15,8 +15,7 @@ paths for: const pInf = Number.POSITIVE_INFINITY; const nInf = Number.NEGATIVE_INFINITY; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function fillRange(arr: any, start = 0) { +function fillRange(arr, start = 0) { const larr = arr; for (let i = 0, len = larr.length; i < len; i += 1) { larr[i] = i + start; @@ -24,8 +23,7 @@ function fillRange(arr: any, start = 0) { return larr; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function fillRand(arr: any) { +function fillRand(arr) { for (let i = 0, len = arr.length; i < len; i += 1) { arr[i] = Math.random(); } @@ -50,22 +48,16 @@ describe("sortArray", () => { describe("finite numbers", () => { [Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) => 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( - // @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable. 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( - // @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable. Type.from([1, 2, 3, 4, 5, 6]) ); const source = fillRand(new Type(1000)); - // @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable. expect(sortArray(Type.from(source))).toMatchObject( - // @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable. Type.from(source).sort() ); }) @@ -138,27 +130,22 @@ describe("sortIndex", () => { describe("finite numbers", () => { [Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) => 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 index1 = fillRange(new Uint32Array(source1.length)); expect(sortIndex(index1, source1)).toMatchObject( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - index1.sort((a: any, b: any) => source1[a] - source1[b]) + index1.sort((a, b) => 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 index2 = fillRange(new Uint32Array(source2.length)); expect(sortIndex(index2, source2)).toMatchObject( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - index2.sort((a: any, b: any) => source1[a] - source1[b]) + index2.sort((a, b) => source1[a] - source1[b]) ); const source3 = fillRand(new Type(1000)); const index3 = fillRange(new Uint32Array(source3.length)); expect(sortIndex(index3, source3)).toMatchObject( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - index3.sort((a: any, b: any) => source1[a] - source1[b]) + index3.sort((a, b) => source1[a] - source1[b]) ); }) ); diff --git a/client/__tests__/util/typedCrossfilter/util.test.ts b/client/__tests__/util/typedCrossfilter/util.test.js similarity index 100% rename from client/__tests__/util/typedCrossfilter/util.test.ts rename to client/__tests__/util/typedCrossfilter/util.test.js diff --git a/client/configuration/babel/babel.dev.js b/client/configuration/babel/babel.dev.js index e86290c5..e67c4382 100644 --- a/client/configuration/babel/babel.dev.js +++ b/client/configuration/babel/babel.dev.js @@ -11,13 +11,13 @@ module.exports = { }, ], "@babel/preset-react", - "@babel/preset-typescript", ], plugins: [ "@babel/plugin-proposal-function-bind", ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }], ["@babel/plugin-proposal-private-methods", { loose: true }], + ["@babel/plugin-proposal-private-property-in-object", { loose: true }], "@babel/plugin-proposal-export-namespace-from", "@babel/plugin-proposal-optional-chaining", "@babel/plugin-proposal-nullish-coalescing-operator", diff --git a/client/configuration/babel/babel.prod.js b/client/configuration/babel/babel.prod.js index d113bc96..6b6d28a8 100644 --- a/client/configuration/babel/babel.prod.js +++ b/client/configuration/babel/babel.prod.js @@ -10,13 +10,13 @@ module.exports = { }, ], "@babel/preset-react", - "@babel/preset-typescript", ], plugins: [ "@babel/plugin-proposal-function-bind", ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }], ["@babel/plugin-proposal-private-methods", { loose: true }], + ["@babel/plugin-proposal-private-property-in-object", { loose: true }], "@babel/plugin-proposal-export-namespace-from", "@babel/plugin-transform-react-constant-elements", "@babel/plugin-transform-runtime", diff --git a/client/configuration/eslint/eslint.js b/client/configuration/eslint/eslint.js index c44a2853..f314f274 100644 --- a/client/configuration/eslint/eslint.js +++ b/client/configuration/eslint/eslint.js @@ -1,10 +1,8 @@ -/* eslint-disable @blueprintjs/classes-constants -- we don't import blueprint here */ module.exports = { root: true, - parser: "@typescript-eslint/parser", + parser: "babel-eslint", extends: [ - "airbnb-typescript", - "plugin:@typescript-eslint/recommended", + "airbnb", "plugin:eslint-comments/recommended", "plugin:@blueprintjs/recommended", "plugin:compat/recommended", @@ -37,50 +35,18 @@ module.exports = { jsx: true, generators: true, }, - // (thuang): Pairing with `tsconfigRootDir`, which points to the directory - // of eslint.js - project: "../../tsconfig.json", - tsconfigRootDir: __dirname, }, rules: { "react/jsx-no-target-blank": "off", "eslint-comments/require-description": ["error"], "no-magic-numbers": "off", - "@typescript-eslint/no-magic-numbers": "off", "no-nested-ternary": "off", "func-style": "off", "arrow-parens": "off", "no-use-before-define": "off", - "@typescript-eslint/no-use-before-define": "off", "react/jsx-filename-extension": "off", "comma-dangle": "off", - "@typescript-eslint/comma-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", "no-console": "off", "spaced-comment": ["error", "always", { exceptions: ["*"] }], @@ -88,7 +54,6 @@ module.exports = { "object-curly-newline": ["error", { consistent: true }], "react/prop-types": [0], "space-before-function-paren": "off", - "@typescript-eslint/space-before-function-paren": "off", "function-paren-newline": "off", "prefer-destructuring": ["error", { object: true, array: false }], "import/prefer-default-export": "off", @@ -107,9 +72,9 @@ module.exports = { }, overrides: [ { - files: ["**/*.test.ts"], + files: ["**/*.test.js"], env: { - jest: true, // now **/*.test.ts files' env has both es6 *and* jest + jest: true, // now **/*.test.js files' env has both es6 *and* jest }, // Can't extend in overrides: https://github.com/eslint/eslint/issues/8813 // "extends": ["plugin:jest/recommended"] @@ -124,4 +89,3 @@ module.exports = { }, ], }; -/* eslint-enable @blueprintjs/classes-constants -- we don't import blueprint here */ diff --git a/client/configuration/lint-staged/lint-staged.config.js b/client/configuration/lint-staged/lint-staged.config.js index 74d52576..2307b978 100644 --- a/client/configuration/lint-staged/lint-staged.config.js +++ b/client/configuration/lint-staged/lint-staged.config.js @@ -1,4 +1,4 @@ module.exports = { - "*.{js,ts,jsx,tsx}": "eslint --fix", + "*.js": "eslint --fix", "**/*": "prettier --write --ignore-unknown", }; diff --git a/client/configuration/webpack/cspHashPlugin.js b/client/configuration/webpack/cspHashPlugin.js index 99d533b1..3b32efc0 100644 --- a/client/configuration/webpack/cspHashPlugin.js +++ b/client/configuration/webpack/cspHashPlugin.js @@ -1,10 +1,6 @@ /* eslint-disable import/no-extraneous-dependencies -- this file is a devDependency*/ -/* eslint-disable @blueprintjs/classes-constants -- we don't import blueprint here */ -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const cheerio = require("cheerio"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const crypto = require("crypto"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const HtmlWebpackPlugin = require("html-webpack-plugin"); const digest = (str) => { @@ -54,5 +50,4 @@ class CspHashPlugin { } module.exports = CspHashPlugin; -/* eslint-enable @blueprintjs/classes-constants -- we don't import blueprint here */ /* eslint-enable import/no-extraneous-dependencies -- enable*/ diff --git a/client/configuration/webpack/obsoleteHTMLTemplate.html b/client/configuration/webpack/obsoleteHTMLTemplate.html index 2283ad3c..d5ca7df4 100644 --- a/client/configuration/webpack/obsoleteHTMLTemplate.html +++ b/client/configuration/webpack/obsoleteHTMLTemplate.html @@ -22,7 +22,7 @@ >
-
+
Unsupported Browser
-
+
cellxgene is currently supported on the following browsers
-
+
Chrome > 60
Firefox ≥ 60
Edge ≥ 79
diff --git a/client/configuration/webpack/webpack.config.dev.js b/client/configuration/webpack/webpack.config.dev.js index d4a69b71..408cb1e0 100644 --- a/client/configuration/webpack/webpack.config.dev.js +++ b/client/configuration/webpack/webpack.config.dev.js @@ -1,23 +1,13 @@ -/* eslint-disable @blueprintjs/classes-constants -- we don't import blueprint here */ -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const path = require("path"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const webpack = require("webpack"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const HtmlWebpackPlugin = require("html-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const FaviconsWebpackPlugin = require("favicons-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const { merge } = require("webpack-merge"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const sharedConfig = require("./webpack.config.shared"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const babelOptions = require("../babel/babel.dev"); const fonts = path.resolve("src/fonts"); @@ -33,7 +23,7 @@ const devConfig = { module: { rules: [ { - test: /\.(ts|js)x?$/, + test: /\.jsx?$/, loader: "babel-loader", options: babelOptions, }, @@ -93,4 +83,3 @@ const devConfig = { }; module.exports = merge(sharedConfig, devConfig); -/* eslint-enable @blueprintjs/classes-constants -- we don't import blueprint here */ diff --git a/client/configuration/webpack/webpack.config.prod.js b/client/configuration/webpack/webpack.config.prod.js index 9d9192ec..f9a63403 100644 --- a/client/configuration/webpack/webpack.config.prod.js +++ b/client/configuration/webpack/webpack.config.prod.js @@ -1,31 +1,18 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const path = require("path"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const webpack = require("webpack"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const HtmlWebpackPlugin = require("html-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const { CleanWebpackPlugin } = require("clean-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const TerserJSPlugin = require("terser-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const CleanCss = require("clean-css"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const FaviconsWebpackPlugin = require("favicons-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const { merge } = require("webpack-merge"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const babelOptions = require("../babel/babel.prod"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const CspHashPlugin = require("./cspHashPlugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const sharedConfig = require("./webpack.config.shared"); const fonts = path.resolve("src/fonts"); @@ -51,7 +38,7 @@ const prodConfig = { module: { rules: [ { - test: /\.(ts|js)x?$/, + test: /\.jsx?$/, loader: "babel-loader", options: babelOptions, }, diff --git a/client/configuration/webpack/webpack.config.shared.js b/client/configuration/webpack/webpack.config.shared.js index 282d1220..0f98b59d 100644 --- a/client/configuration/webpack/webpack.config.shared.js +++ b/client/configuration/webpack/webpack.config.shared.js @@ -1,13 +1,8 @@ -/* eslint-disable @blueprintjs/classes-constants -- we don't import blueprint here */ -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const path = require("path"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const fs = require("fs"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. const ObsoleteWebpackPlugin = require("obsolete-webpack-plugin"); -// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS. +// eslint-disable-next-line @blueprintjs/classes-constants -- incorrect match const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin"); const src = path.resolve("src"); @@ -34,9 +29,6 @@ module.exports = { path: path.resolve("build"), publicPath, }, - resolve: { - extensions: [".ts", ".tsx", "..."], - }, module: { rules: [ { @@ -80,4 +72,3 @@ module.exports = { }), ], }; -/* eslint-enable @blueprintjs/classes-constants -- we don't import blueprint here */ diff --git a/client/package-lock.json b/client/package-lock.json index de350e24..c44e72c5 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -59,38 +59,10 @@ "@babel/plugin-transform-runtime": "^7.13.15", "@babel/preset-env": "^7.13.15", "@babel/preset-react": "^7.13.13", - "@babel/preset-typescript": "^7.14.5", "@babel/register": "^7.13.16", "@babel/runtime": "^7.13.16", "@blueprintjs/eslint-plugin": "^0.3.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-jest": "^26.1.0", "babel-loader": "^8.1.0", @@ -102,7 +74,7 @@ "codecov": "^3.7.1", "css-loader": "^5.2.4", "eslint": "^7.24.0", - "eslint-config-airbnb-typescript": "^12.3.1", + "eslint-config-airbnb": "^18.2.0", "eslint-config-prettier": "^8.2.0", "eslint-loader": "^4.0.2", "eslint-plugin-compat": "^3.8.0", @@ -142,7 +114,6 @@ "script-ext-html-webpack-plugin": "^2.1.4", "serve-favicon": "^2.5.0", "terser-webpack-plugin": "^5.1.1", - "typescript": "^4.3.5", "webpack": "^5.34.0", "webpack-cli": "^4.6.0", "webpack-dev-middleware": "^4.1.0", @@ -213,11 +184,11 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-sdk/abort-controller": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.23.0.tgz", - "integrity": "sha512-M69Sdoi6TH2UrnXKKNJNDaW6iCqpras7w274CZq4NjFOGwrb23KO2Aexgxr3g3hsUidfjuA38oFbHgC8odFrIQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.25.0.tgz", + "integrity": "sha512-uEVKqKkPVz6atbCxCNJY5O7V+ieSK8crUswXo8/WePyEbGEgxJ4t9x/WG4lV8kBjelmvQHDR4GqfJmb5Sh9xSg==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -225,38 +196,38 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.24.0.tgz", - "integrity": "sha512-zpu7XGlXlUnYqIeNiCH+mMmHLKyqIpIyi+lLGly0PYuPPmPOj0nB+X++H927maeoDHyKjfU+GP6863CypxhA0g==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.27.0.tgz", + "integrity": "sha512-WsVytEQKOjDKZKszm0Mfd3sCvUG1fYr2iu5yOnMaeAQQjCNw5nQ0tif0mC0suVG3847DvBJ9ajNab82EI5R1PQ==", "dependencies": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/client-sts": "3.24.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/credential-provider-node": "3.24.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/client-sts": "3.27.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/credential-provider-node": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "tslib": "^2.3.0", @@ -267,35 +238,35 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.24.0.tgz", - "integrity": "sha512-gee+zjIUiDayRhDsUakB/9h1crH419pgDWdZ91s/jXkOVXlCRoVaArmYPUBBWkVvGMoSvM6BVvojf2cWViA5FA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.27.0.tgz", + "integrity": "sha512-/Op+OaQgcAG/FyyqJc2NVfIJWEd1cTWIl8gBWSTUugrhhd5rMnAtg3u5ds/tYUimVQJv03z4bDjbI0Rnv/t6XQ==", "dependencies": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "tslib": "^2.3.0" @@ -305,38 +276,38 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.24.0.tgz", - "integrity": "sha512-GifVktvnDQlEJfspoERAFhS+vm7b0OmK3ACN/a6/wFc3hXEGIcS/WRzfRERXJfYg8Ial4Sr8bxDXMW30jPk3fQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.27.0.tgz", + "integrity": "sha512-QagsjULn6eacR/IL9d/nky17jUcqnbeShrHGrAyOhAXtehG3g2kkFcGbFy30iNw8gl1LteZL9dslpPFdWIEI1A==", "dependencies": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/credential-provider-node": "3.24.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-sdk-sts": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/credential-provider-node": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-sdk-sts": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "entities": "2.2.0", @@ -348,12 +319,12 @@ } }, "node_modules/@aws-sdk/config-resolver": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.23.0.tgz", - "integrity": "sha512-acCxrAymwx81XELBO/d1VBWaHOldxqbmxDAMfvOfUYN+CYXWIFYpY1VCWuAeWig7Dy18QEJQ2pHwQlFxmilA7w==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.27.0.tgz", + "integrity": "sha512-gc7dfBzdmUHJamMjOc0bzAkIm3VUIK9kbLQSy0+nfjT641+AYvXO3qpjR6ywvutsbKhBg5kyGn/4QhyRxg61OQ==", "dependencies": { - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -361,12 +332,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.23.0.tgz", - "integrity": "sha512-ljYkVATha4BdecVvYeW1WuzoAAwfM/i7p9Wmx1RY3Rb0AGwIFX2GjtoBPhS3EbCRTzQIhUr4zfIelVVVxIS6bA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.27.0.tgz", + "integrity": "sha512-IbPdlYl0A5GcpuT394cJceexxo0tzUzC7jIUxqL8gNbB/MIXC5ZlkeX9Z7bYloNb8SXk7GumXyQTsK1CchUvQA==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -374,12 +345,14 @@ } }, "node_modules/@aws-sdk/credential-provider-imds": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.23.0.tgz", - "integrity": "sha512-jD1EkoVDApKZJwOLACTrnxhDmQiVF1qMM+GMnoY4bMk1p1sfZYNKs6VkaY2LGUWXxkesj1aiMFxbwyWmu8SQbQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.27.0.tgz", + "integrity": "sha512-rhzlEvxiB7ecpVDl3NkjP1vPmqs+HHmqNXrK4efOYshwIbu+/h3xPePQMBOQ0AGezYn3k/iumoXXysVhVqtwUA==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -387,17 +360,17 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.24.0.tgz", - "integrity": "sha512-EwXEo0MqOjF28lIk1S2wo0HwIioUDC1LbFukd7mo3lIG47yS7Qllw7HIyhLzO5ayI5AouKP9nnLElgHVz81seg==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.27.0.tgz", + "integrity": "sha512-jvWUDz6nFqUvjmPRebwf1mWsOZ+inmZNQxz20DC/ROCRfGF1y8Yqf7KgCJy8MQOlDdTA4lPS+w6OJ0J/OOGbPg==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.23.0", - "@aws-sdk/credential-provider-imds": "3.23.0", - "@aws-sdk/credential-provider-sso": "3.24.0", - "@aws-sdk/credential-provider-web-identity": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/credential-provider-env": "3.27.0", + "@aws-sdk/credential-provider-imds": "3.27.0", + "@aws-sdk/credential-provider-sso": "3.27.0", + "@aws-sdk/credential-provider-web-identity": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" }, @@ -406,19 +379,19 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.24.0.tgz", - "integrity": "sha512-sQQDciLXYErBEIkphBlvIRh0shZe9iK6KqtpT5Sueu6ADEOIQlgF7Kw5/N9BhPQ8pYORibCH0eIabPD+u3hr9w==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.27.0.tgz", + "integrity": "sha512-GfCDX/AA7EJKyVGmNnh3wngWfEWFkuNJyend6FLN+81s3kUpXTkILuZCwQrD9AyjBYR2ksv0t929nW2fBUGT9Q==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.23.0", - "@aws-sdk/credential-provider-imds": "3.23.0", - "@aws-sdk/credential-provider-ini": "3.24.0", - "@aws-sdk/credential-provider-process": "3.23.0", - "@aws-sdk/credential-provider-sso": "3.24.0", - "@aws-sdk/credential-provider-web-identity": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/credential-provider-env": "3.27.0", + "@aws-sdk/credential-provider-imds": "3.27.0", + "@aws-sdk/credential-provider-ini": "3.27.0", + "@aws-sdk/credential-provider-process": "3.27.0", + "@aws-sdk/credential-provider-sso": "3.27.0", + "@aws-sdk/credential-provider-web-identity": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" }, @@ -427,13 +400,13 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.23.0.tgz", - "integrity": "sha512-xba0u86nS5MtH3FQKSbTOEaoHjqpoj6NyonZEy0O5i9KO0NHf+bZwlmI/pe54SOE9uSrDKHfXB6dsftVIqXtFQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.27.0.tgz", + "integrity": "sha512-F9pqKKnd5+fwoldVQJX9uLbDyPyIDnCpZGbiTw6BZANZM1qhjoEn7rNE5g2h0tkeq4dWMA9bANKMR4j3YhTpXw==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" }, @@ -442,14 +415,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.24.0.tgz", - "integrity": "sha512-HZomNXn1kw/5M1AHFY7Rcnayl/7tXKG+67m7W3V9+G9+xzEjW5229y8VeZkoNUhVHh5rwvqd3fKKHx1g9sZsUA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.27.0.tgz", + "integrity": "sha512-yXyy+/FYFtpnRmPBiw5rxwSQBj1pcI0R+z77EA8a8+tozZPjsIri+xBsU62DtIlv/2yVb/goPgw+w2vg0L4NFw==", "dependencies": { - "@aws-sdk/client-sso": "3.24.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/client-sso": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" }, @@ -458,12 +431,12 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.23.0.tgz", - "integrity": "sha512-GbDw2izWfb4KG62V6MBTOKmDAhbexbemxJsR0rMlZxW/dEYQh/r8Nk+m7evAUakNMJGm4fcAZGxey+orReq1VQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.27.0.tgz", + "integrity": "sha512-FYvDzB4UqmJjY+ZZoIAPM1EFK9/RdNn1VT5xvDcebQe7xKOVUG1tZbOA4rVZ3MUcxfyRqp7Ou/AhIWu/9RSt2Q==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -471,23 +444,23 @@ } }, "node_modules/@aws-sdk/fetch-http-handler": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.23.0.tgz", - "integrity": "sha512-gjToPkLlVOO8bHKhyw+d4mIX4OJEabqIFYbRFRDSm11LVLAAEc4pIFPYpMNWzrmDEnCxoGAcqfzP0m+0jChVCw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.25.0.tgz", + "integrity": "sha512-792kkbfSRBdiFb7Q2cDJts9MKxzAwuQSwUIwRKAOMazU8HkKbKnXXAFSsK3T7VasOFOh7O7YEGN0q9UgEw1q+g==", "dependencies": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/querystring-builder": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/querystring-builder": "3.25.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "tslib": "^2.3.0" } }, "node_modules/@aws-sdk/hash-node": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.23.0.tgz", - "integrity": "sha512-yah+vNhKv6jpJR5qHYGc/AIAWwR9Ah9NplAq8cltMsPuI38u/aSlbcEIDwsRz3V1MDA89f/+qY3OHBfQw5kLVw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.25.0.tgz", + "integrity": "sha512-qRn6iqG9VLt8D29SBABcbauDLn92ssMjtpyVApiOhDYyFm2VA2avomOHD6y2PRBMwM5FMQAygZbpA2HIN2F96w==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-buffer-from": "3.23.0", "tslib": "^2.3.0" }, @@ -496,11 +469,11 @@ } }, "node_modules/@aws-sdk/invalid-dependency": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.23.0.tgz", - "integrity": "sha512-5VqL7crIEtXj+lBwh3kKdMMlejjumjJQ5uLYNSCE/jNS5YjnbhAfO+fyzMO50IhcSuG4Ev6i1DEezN9BmYdeXA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.25.0.tgz", + "integrity": "sha512-ZBXjBAF2JSiO/wGBa1oaXsd1q5YG3diS8TfIUMXeQoe9O66R5LGoGOQeAbB/JjlwFot6DZfAcfocvl6CtWwqkw==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, @@ -516,12 +489,12 @@ } }, "node_modules/@aws-sdk/middleware-content-length": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.23.0.tgz", - "integrity": "sha512-ooyNeXZUtI16Qh/HfcwLWn7NB2HvM/XEajaQmVIJXbVy/D2+N82+0Jo2hY3DouuIJjoEv/KZ5Uia/cgCdfHrHQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.25.0.tgz", + "integrity": "sha512-uOXus0MmZi/mucRIr5yfwM1vDhYG66CujNfnhyEaq5f4kcDA1Q5qPWSn9dkQPV9JWTZK3WTuYiOPSgtmlAYTAg==", "dependencies": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -529,12 +502,12 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.23.0.tgz", - "integrity": "sha512-bHqQbwY3guUr+AWcrerHIh1ONgqhV8W85+H7MYlt0V5/Kom0+ectR7yZZRt90PDMZ8OsW4+f5jTIURFMLtPbDA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.25.0.tgz", + "integrity": "sha512-xKD/CfsUS3ul2VaQ3IgIUXgA7jU2/Guo/DUhYKrLZTOxm0nuvsIFw0RqSCtRBCLptE5Qi+unkc1LcFDbfqrRbg==", "dependencies": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -542,11 +515,11 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.23.0.tgz", - "integrity": "sha512-0z0ULcxllHO6xz1VeX/ekmg/LpNFL8nFbRH067s2KaimBeCUZ0CA2RwTpi9IY74tikmZAjerASb8eMgI+L/d7A==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.25.0.tgz", + "integrity": "sha512-M1F7BlAsDKoEM8hBaU2pHlLSM40rzzgtZ6jFNhfmTwGcjxe1N7JXCH5QPa7aI8wnJq2RoIRHVfVsUH4GwvOZnA==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -554,13 +527,13 @@ } }, "node_modules/@aws-sdk/middleware-retry": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.23.0.tgz", - "integrity": "sha512-NimiKrP90+aW62QmkOrhQAZjrwjOQuWye2POzdetSrBHpnwj2KQWNBjcRwjkGt53krPcDyCySjIw+ivTRYdxWw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.27.0.tgz", + "integrity": "sha512-H57NP27qOxgbPRwCFkBYtAJylhAOWKSv3/TsCpDNnrb3Z0pqKUQH9mLC8hRGTRplkA7SDGfiuf9bsoNhZ3HFwQ==", "dependencies": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/service-error-classification": "3.22.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/service-error-classification": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0", "uuid": "^8.3.2" }, @@ -569,15 +542,15 @@ } }, "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.23.0.tgz", - "integrity": "sha512-Rufzuqp4neVsyll9Ya9j+zpoK1fXrujBX6XRR5fRU3SsoAh5YWiUMrkxYxzTN+TLeXmyhCzmH/RuX2hgjMK0VQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.27.0.tgz", + "integrity": "sha512-4geCMczCujTz4GWSrwKhxEW9rYikp5NrLcIpHI0NjthQQfa8T4/D1WSsSnW3JNmQcMgQXeC9h8jTn0dOE4EhUw==", "dependencies": { - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -585,11 +558,11 @@ } }, "node_modules/@aws-sdk/middleware-serde": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.23.0.tgz", - "integrity": "sha512-gNNMOo6Phm/BAnLsXvFfu4PHxKzN1saT3lNkODY2qKB1b4IoFNdMfHMo3jH4sbx7QYoM81qMXKr7aLp1BzTHtw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.25.0.tgz", + "integrity": "sha512-065Kugo8yXzBkcVAxctxFCHKlHcINnaQRsJ8ifvgc+UOEgvTG9+LfGWDwfdgarW9CkF7RkCoZOyaqFsO+HJWsg==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -597,14 +570,14 @@ } }, "node_modules/@aws-sdk/middleware-signing": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.23.0.tgz", - "integrity": "sha512-cTozWnc8HLxLjHYU10+uqE4RqXYmmCJqoEKiSzJH7f8n20Pr9ly3rv3/9AfbqPth1PXsg0xHYq/ovCvq6RiaYA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.27.0.tgz", + "integrity": "sha512-eOXwKOFuCIGAW3wZO9Cyh+z7swZYTq8BiBDjwWu6u0UBb5B/zMiq1z1LDa88iZY200O3Zip8+6RZV7LLd3XH+Q==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -612,9 +585,9 @@ } }, "node_modules/@aws-sdk/middleware-stack": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.23.0.tgz", - "integrity": "sha512-lk4u8wDajJ+VBXVWpzqaRUUJibt1YxsIciwLeZymilAZW5L9VtchUW9fmRpaZX8QHFGGkGuwZjtxlX6MeGXK4w==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.25.0.tgz", + "integrity": "sha512-s2VgdsasOVKHY3/SIGsw9AeZMMsdcIbBGWim9n5IO3j8C8y54EdRLVCEja8ePvMDZKIzuummwatYPHaUrnqPtQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -623,12 +596,12 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.23.0.tgz", - "integrity": "sha512-cwOypi0no2Nsrw1N3VGe/0XgbNl487Wn4jgKZvj+nxdSWh4HQMWpoTLB3YZtzro+J7uVK6X7W+QxBU20+Ypg1g==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.25.0.tgz", + "integrity": "sha512-HXd/Qknq8Cp7fzJYU7jDDpN7ReJ3arUrnt+dAPNaDDrhmrBbCZp+24UXN6X6DAj0JICRoRuF/l7KxjwdF5FShw==", "dependencies": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -636,13 +609,13 @@ } }, "node_modules/@aws-sdk/node-config-provider": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.23.0.tgz", - "integrity": "sha512-OyhyqTXUy5HxPu2c1aCYFHKQGjf4uzjby9AteMhRJfa6cehuVODi3KEv7PyZmJQcYI0Pw9ZnoHqVrTNsUEC2YQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.27.0.tgz", + "integrity": "sha512-5jeCLV7NI/ouQCMGDnGbxpCBhGirksXY55uvAaeysMxzjJLmPDwOZUD1gMhfYe8lxvktwhAndOdPQofWwTFUoQ==", "dependencies": { - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -650,14 +623,14 @@ } }, "node_modules/@aws-sdk/node-http-handler": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.23.0.tgz", - "integrity": "sha512-amvf0lwldUrr+CFtIeMZoNVmv34Fx3zwqobT5WuxtfRWbvSRALMw0LW/oXwoT+4WayM6sIwcIwSG1ZVGCjD0fA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.25.0.tgz", + "integrity": "sha512-zVeAM/bXewZiuMtcUZI/xGDID6knkzOv73ueVkzUbP0Ki8bfao7diR3hMbIt5Fy/r8cAVjJce9v6zFqo4sr1WA==", "dependencies": { - "@aws-sdk/abort-controller": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/querystring-builder": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/abort-controller": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/querystring-builder": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -665,11 +638,11 @@ } }, "node_modules/@aws-sdk/property-provider": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.23.0.tgz", - "integrity": "sha512-GjFtmFHVzO4BeLRselGirt32cyorP1aRbD+ID4Zhz4RLxa9Nun766s8lqp7EcR/v9pSGdP1Xec3no8ALV3lXmw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.27.0.tgz", + "integrity": "sha512-8vovVNldgJwCpUfehdwUPwvzfUPB7TEW/tcTgrkLQW/cpEULbRrymtiZrzSkBLspNw2iU5d3FpQxE61s1ou0UA==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -677,11 +650,11 @@ } }, "node_modules/@aws-sdk/protocol-http": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.23.0.tgz", - "integrity": "sha512-JTsq/UU/wTyeCMPVar2xSsMVFf72IK0L7dXbbS7ZHcBV6JAfM/wVTym8/s3mQGM6Kx/c6Wtn+J/5syDx56CV2g==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.25.0.tgz", + "integrity": "sha512-4Jebt5G8uIFa+HZO7KOgOtA66E/CXysQekiV5dfAsU8ca+rX5PB6qhpWZ2unX/l6He+oDQ0zMoW70JkNiP4/4w==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -689,11 +662,11 @@ } }, "node_modules/@aws-sdk/querystring-builder": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.23.0.tgz", - "integrity": "sha512-MfQknhgMT9tul0VrxmLBDKlV7Ls2/kEJyprWXUWzCUBMUZ6M+FtOMJhjP90qTbsNvlsEVQgTlS/cDsNVrAUR3A==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.25.0.tgz", + "integrity": "sha512-o/R3/viOxjWckI+kepkxJSL7fIdg1hHYOW/rOpo9HbXS0CJrHVnB8vlBb+Xwl1IFyY2gg+5YZTjiufcgpgRBkw==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-uri-escape": "3.23.0", "tslib": "^2.3.0" }, @@ -702,11 +675,11 @@ } }, "node_modules/@aws-sdk/querystring-parser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.23.0.tgz", - "integrity": "sha512-pMEN+rE08QhixRfWEBuQwnOGuGiRjH5++mmyQTUIvEgKk/rnyAkUlrySv775jvrEQlCXH8yqMuHdutF8rHkHGA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.25.0.tgz", + "integrity": "sha512-FCNyaOLFLVS5j43MhVA7/VJUDX0t/9RyNTNulHgzFjj6ffsgqcY0uwUq1RO3QCL4asl56zOrLVJgK+Z7wMbvFg==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -714,9 +687,9 @@ } }, "node_modules/@aws-sdk/service-error-classification": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.22.0.tgz", - "integrity": "sha512-6ytFFoU8guAljwpmQTvZNf//cTurdumeLlAmQ8RJsbX3y5DGlpG2dfq7mpYJudtJtCQTwPYtaG5Xva460T2CqA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.25.0.tgz", + "integrity": "sha512-66FfIab87LnnHtOLrGrVOht9Pw6lE8appyOpBdtoeoU5DP7ARSWuDdsYmKdGdRCWvn/RaVFbSYua9k0M1WsGqg==", "engines": { "node": ">= 10.0.0" } @@ -733,12 +706,12 @@ } }, "node_modules/@aws-sdk/signature-v4": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.23.0.tgz", - "integrity": "sha512-3smgG/6LcK8SjVqWzroAgSFOF8HKp4/LtOQQBtPkI04nTMVP4zmE5hsVQEZv33h5UKWkUpwQRBTCtfFZTq/Jvw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.25.0.tgz", + "integrity": "sha512-6KDRRz9XVrj9RxrBLC6dzfnb2TDl3CjIzcNpLdRuKFgzEEdwV+5D+EZuAQU3MuHG5pWTIwG72k/dmCbJ2MDPUQ==", "dependencies": { "@aws-sdk/is-array-buffer": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-hex-encoding": "3.23.0", "@aws-sdk/util-uri-escape": "3.23.0", "tslib": "^2.3.0" @@ -748,12 +721,12 @@ } }, "node_modules/@aws-sdk/smithy-client": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.24.0.tgz", - "integrity": "sha512-HFoRcO8eqnaN5+r5dPqP3t8ks0gBDhn0ClzTN8BloFwVVc0Wu7N1yZYp/NxLviwqC9X+R+ZbAJn+zjac24zgdw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.27.0.tgz", + "integrity": "sha512-PpsSDUsRqw8HGuXv+AR2UzhVUJz4APM7K6Br8TTDPKvDwQtXkT5GROXRyAwU+htPcOHq006lS5EiF343y0HRvg==", "dependencies": { - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -761,20 +734,20 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.22.0.tgz", - "integrity": "sha512-dGJBPbWm+YT+D5YIiqK3Z1xWzWShWgSxL1gPS9+vKNY2ld2TvtoiRhFy8NQG2jnC+eG/+WNeZS6ZxzLvEbQyTQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.25.0.tgz", + "integrity": "sha512-vS0+cTKwj6CujlR07HmeEBxzWPWSrdmZMYnxn/QC9KW9dFu0lsyCGSCqWsFluI6GI0flsnYYWNkP5y4bfD9tqg==", "engines": { "node": ">= 10.0.0" } }, "node_modules/@aws-sdk/url-parser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.23.0.tgz", - "integrity": "sha512-uU4BDX0eilGlMuz8qDlNzcH3k4WTZWgMnBuJ9+TdxTXNiLvC+X9HBjVmB2Nr+3mEJhhrRc/8mTrleJvcl60Pyg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.25.0.tgz", + "integrity": "sha512-qZ3Vq0NjHsE7Qq6R5NVRswIAsiyYjCDnAV+/Vt4jU/K0V3mGumiasiJyRyblW4Da8R6kfcJk0mHSMFRJfoHh8Q==", "dependencies": { - "@aws-sdk/querystring-parser": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/querystring-parser": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, @@ -875,22 +848,22 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.23.0.tgz", - "integrity": "sha512-FIjcCdvnUuOBMQgvPZ04Hk28Qy+xJDrtXeWm/7xKJ1K7NRucJWjmC+0OU0uw9A7VOCHf08nk9xniZhAGXs1wJg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.25.0.tgz", + "integrity": "sha512-qGqiWfs49NRmQVXPsBXgMRVkjDZocicU0V2wak98e0t7TOI+KmP8hnwsTkE6c4KwhsFOOUhAzjn5zk3kOwi6tQ==", "dependencies": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "bowser": "^2.11.0", "tslib": "^2.3.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.23.0.tgz", - "integrity": "sha512-6okok4u13uYRIYdgFZ4dCsowf5vKh+ZxkfVSwvnZO3XAaGEhmIkM3+JKIQjcxLJ+Mt0ssMSJwNMz5oOBSlXPeQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.27.0.tgz", + "integrity": "sha512-jigZzAuhEnaLFeYEDGKQq8tas8OsT6qI7WAm/UnCXqtLhdnIu7u1yPhXk+TjI7SSn4Z6zP6Oh1qtFxzhpPmdoQ==", "dependencies": { - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" }, "engines": { @@ -930,29 +903,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", - "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz", - "integrity": "sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", + "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.8", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.8", + "@babel/generator": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", + "@babel/helper-module-transforms": "^7.15.0", "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.14.8", + "@babel/parser": "^7.15.0", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -969,12 +942,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", - "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", "dev": true, "dependencies": { - "@babel/types": "^7.14.8", + "@babel/types": "^7.15.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -1008,12 +981,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", - "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", + "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", "browserslist": "^4.16.6", "semver": "^6.3.0" @@ -1026,16 +999,16 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.8.tgz", - "integrity": "sha512-bpYvH8zJBWzeqi1o+co8qOrw+EXzQ/0c74gVmY205AWXy9nifHrOg77y+1zwxX5lXE7Icq4sPlSQ4O2kWBrteQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", + "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.14.7", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-split-export-declaration": "^7.14.5" }, "engines": { @@ -1131,12 +1104,12 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", - "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", + "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", "dev": true, "dependencies": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.0" }, "engines": { "node": ">=6.9.0" @@ -1155,19 +1128,19 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz", - "integrity": "sha512-RyE+NFOjXn5A9YU1dkpeBaduagTlZ0+fccnIcAGbv1KGUlReBj7utF7oEth8IdIBQPcux0DDgW5MFBH2xu9KcA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-simple-access": "^7.14.8", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.8", + "@babel/helper-validator-identifier": "^7.14.9", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" }, "engines": { "node": ">=6.9.0" @@ -1209,15 +1182,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", - "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", + "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" }, "engines": { "node": ">=6.9.0" @@ -1260,9 +1233,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz", - "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1293,14 +1266,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", + "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", "dev": true, "dependencies": { "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" }, "engines": { "node": ">=6.9.0" @@ -1392,9 +1365,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.8.tgz", - "integrity": "sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1421,9 +1394,9 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", - "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", + "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5", @@ -1947,21 +1920,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", @@ -2010,9 +1968,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", - "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", + "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -2025,9 +1983,9 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", - "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", + "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.14.5", @@ -2201,14 +2159,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", - "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", + "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-module-transforms": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-simple-access": "^7.14.8", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -2254,9 +2212,9 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", - "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", + "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" @@ -2345,9 +2303,9 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.5.tgz", - "integrity": "sha512-07aqY1ChoPgIxsuDviptRpVkWCSbXWmzQqcgy65C6YSFOfPFvb/DX3bBRHh7pCd/PMEEYHYWUTSVkCbkVainYQ==", + "version": "7.15.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", + "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -2360,16 +2318,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.5.tgz", - "integrity": "sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", + "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-module-imports": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/types": "^7.14.9" }, "engines": { "node": ">=6.9.0" @@ -2440,9 +2398,9 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", - "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz", + "integrity": "sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.14.5", @@ -2535,23 +2493,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz", - "integrity": "sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.14.6", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", @@ -2584,17 +2525,17 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.8.tgz", - "integrity": "sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", + "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.14.7", - "@babel/helper-compilation-targets": "^7.14.5", + "@babel/compat-data": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.7", + "@babel/plugin-proposal-async-generator-functions": "^7.14.9", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-class-static-block": "^7.14.5", "@babel/plugin-proposal-dynamic-import": "^7.14.5", @@ -2627,7 +2568,7 @@ "@babel/plugin-transform-async-to-generator": "^7.14.5", "@babel/plugin-transform-block-scoped-functions": "^7.14.5", "@babel/plugin-transform-block-scoping": "^7.14.5", - "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.9", "@babel/plugin-transform-computed-properties": "^7.14.5", "@babel/plugin-transform-destructuring": "^7.14.7", "@babel/plugin-transform-dotall-regex": "^7.14.5", @@ -2638,10 +2579,10 @@ "@babel/plugin-transform-literals": "^7.14.5", "@babel/plugin-transform-member-expression-literals": "^7.14.5", "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.15.0", "@babel/plugin-transform-modules-systemjs": "^7.14.5", "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", "@babel/plugin-transform-new-target": "^7.14.5", "@babel/plugin-transform-object-super": "^7.14.5", "@babel/plugin-transform-parameters": "^7.14.5", @@ -2656,11 +2597,11 @@ "@babel/plugin-transform-unicode-escapes": "^7.14.5", "@babel/plugin-transform-unicode-regex": "^7.14.5", "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.14.8", + "@babel/types": "^7.15.0", "babel-plugin-polyfill-corejs2": "^0.2.2", "babel-plugin-polyfill-corejs3": "^0.2.2", "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.15.0", + "core-js-compat": "^3.16.0", "semver": "^6.3.0" }, "engines": { @@ -2706,27 +2647,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz", - "integrity": "sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/register": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.14.5.tgz", - "integrity": "sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.15.3.tgz", + "integrity": "sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", @@ -2743,9 +2667,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", + "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -2754,9 +2678,9 @@ } }, "node_modules/@babel/runtime-corejs2": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.14.8.tgz", - "integrity": "sha512-Jj4fkQPFp73ia9y6BctEX5ypA1icbOVPtc9l0T1VnAv8EmzaN/Lm/WvnKNve1610VvHV69SLihpu9tHnVziBvw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.15.3.tgz", + "integrity": "sha512-iG7ypZmrdoKP1ckFurS8z97TR+Bqd6KaDsLQ9DiC/Rdxmrvy1nsCDlgfLNKfalbg9sFWdmIdNf+Hg+19XysSFg==", "dev": true, "dependencies": { "core-js": "^2.6.5", @@ -2775,12 +2699,12 @@ "hasInstallScript": true }, "node_modules/@babel/runtime-corejs3": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.8.tgz", - "integrity": "sha512-4dMD5QRBkumn45oweR0SxoNtt15oz3BUBAQ8cIx7HJqZTtE8zjpM0My8aHJHVnyf4XfRg6DNzaE1080WLBiC1w==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz", + "integrity": "sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==", "dev": true, "dependencies": { - "core-js-pure": "^3.15.0", + "core-js-pure": "^3.16.0", "regenerator-runtime": "^0.13.4" }, "engines": { @@ -2802,18 +2726,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.8.tgz", - "integrity": "sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.8", + "@babel/generator": "^7.15.0", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.8", - "@babel/types": "^7.14.8", + "@babel/parser": "^7.15.0", + "@babel/types": "^7.15.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2822,12 +2746,12 @@ } }, "node_modules/@babel/types": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.8.tgz", - "integrity": "sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.8", + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2840,12 +2764,18 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@blueprintjs/colors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/colors/-/colors-1.0.0.tgz", + "integrity": "sha512-eJh111ucz8HYxLBON6ADkAGQQBACqdbX6Zws/GpuiTkeCFJ3IAjZdBpk7IM7/Y5XuGuSS1ujwjnLDOEtyywtKw==" + }, "node_modules/@blueprintjs/core": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.47.0.tgz", - "integrity": "sha512-u+bfmCyPXwKZMnwY4+e/iWjO2vDUvr8hA8ydmV0afyvcEe7Sh85UPEorIgQ/CBuRIbVMNm8FpLsFzDxgkfrCNA==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.48.0.tgz", + "integrity": "sha512-tuAL3dZrNaTq36RRy6O86wjmkiLt8LwHkleZ1zUcn/DC3cXsM3dSsRpV3f662bcEiAXMPeGemSC3tqv6uZCeLg==", "dependencies": { - "@blueprintjs/icons": "^3.27.0", + "@blueprintjs/colors": "^1.0.0", + "@blueprintjs/icons": "^3.28.0", "@types/dom4": "^2.0.1", "classnames": "^2.2", "dom4": "^2.1.5", @@ -2866,23 +2796,6 @@ "react-dom": "^15.3.0 || 16 || 17" } }, - "node_modules/@blueprintjs/core/node_modules/react-popper": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", - "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "@hypnosphi/create-react-context": "^0.3.1", - "deep-equal": "^1.1.1", - "popper.js": "^1.14.4", - "prop-types": "^15.6.1", - "typed-styles": "^0.0.7", - "warning": "^4.0.2" - }, - "peerDependencies": { - "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@blueprintjs/core/node_modules/tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -2899,9 +2812,9 @@ } }, "node_modules/@blueprintjs/icons": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.27.0.tgz", - "integrity": "sha512-ItRioyrr2s70chclj5q38HS9omKOa15b3JZXv9JcMIFz+6w6rAcoAH7DA+5xIs27bFjax/SdAZp/eYXSw0+QpA==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.28.0.tgz", + "integrity": "sha512-gDvvU2ljV4NXsY5ofKcs1ChXAgmqNp/DIMu2uJIJmXhSXfP6JDd4qbnbGMsP3FmLTaqQP3E9oBZqAG/FRB8VmQ==", "dependencies": { "classnames": "^2.2", "tslib": "~1.13.0" @@ -2928,17 +2841,30 @@ "react": "^16.8.0 || ^17" } }, + "node_modules/@blueprintjs/popover2/node_modules/react-popper": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", + "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17" + } + }, "node_modules/@blueprintjs/popover2/node_modules/tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "node_modules/@blueprintjs/select": { - "version": "3.16.6", - "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.16.6.tgz", - "integrity": "sha512-lg2duuzlRw18+pbET6vlRY/TVSuuSI6wI4DObUiBAfU7G3fMa6d10Sp+0Yn00XaMPQ5y3MGn1gz0EbIJ3/A5OA==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.17.0.tgz", + "integrity": "sha512-38jvSt1zGOJuw6Vj3BrDn1ojZCI+U5UV8xEupGPTEVyszE7RwFoF8l1iDTLbiPwLV5DSOxTN0B6mxeSPX45OQw==", "dependencies": { - "@blueprintjs/core": "^3.47.0", + "@blueprintjs/core": "^3.48.0", "classnames": "^2.2", "tslib": "~1.13.0" }, @@ -2998,9 +2924,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3804,9 +3730,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.13.tgz", - "integrity": "sha512-YCclX4FGCVMkdIFykkyrgBkERN1huqU+Lyr767mbTuSVtj2LKfXpVwv/D0C1ZaefRvpinRJ/Xfy0mBNi7XIs0w==", + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.14.tgz", + "integrity": "sha512-n2RC9d6XatVbWFdHLimzzUJxJ1KY8LdjqrW6YvGPiRmsHkhOUx74/Ct10x5Yo7bC/Jvqx7cDEW8IMPv/+vwEzA==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -3845,9 +3771,9 @@ } }, "node_modules/@popperjs/core": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz", - "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz", + "integrity": "sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -3875,12 +3801,12 @@ } }, "node_modules/@sentry/webpack-plugin": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.16.0.tgz", - "integrity": "sha512-Ax0QZ3a+LFYU876Si2HElPYSj+mX3vinvzH+o9F1g/5T2Z3HqITnX6gg+zVfLFsE819PN9KeLpmoHtO352dlmQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.17.1.tgz", + "integrity": "sha512-L47a0hxano4a+9jbvQSBzHCT1Ph8fYAvGGUvFg8qc69yXS9si5lXRNIH/pavN6mqJjhQjAcEsEp+vxgvT4xZDQ==", "dev": true, "dependencies": { - "@sentry/cli": "^1.67.1" + "@sentry/cli": "^1.68.0" }, "engines": { "node": ">= 8" @@ -3975,259 +3901,6 @@ "@babel/types": "^7.3.0" } }, - "node_modules/@types/d3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.0.0.tgz", - "integrity": "sha512-7rMMuS5unvbvFCJXAkQXIxWTo2OUlmVXN5q7sfQFesuVICY55PSP6hhbUhWjTTNpfTTB3iLALsIYDFe7KUNABw==", - "dev": true, - "dependencies": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" - } - }, - "node_modules/@types/d3-array": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.1.tgz", - "integrity": "sha512-D/G7oG0czeszALrkdUiV68CDiHDxXf+M2mLVqAyKktGd12VKQQljj1sHJGBKjcK4jRH1biBd6ZPQPHpJ0mNa0w==", - "dev": true - }, - "node_modules/@types/d3-axis": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.1.tgz", - "integrity": "sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==", - "dev": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-brush": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.1.tgz", - "integrity": "sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==", - "dev": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==", - "dev": true - }, - "node_modules/@types/d3-color": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.0.2.tgz", - "integrity": "sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ==", - "dev": true - }, - "node_modules/@types/d3-contour": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.1.tgz", - "integrity": "sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==", - "dev": true, - "dependencies": { - "@types/d3-array": "*", - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-delaunay": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.0.tgz", - "integrity": "sha512-iGm7ZaGLq11RK3e69VeMM6Oqj2SjKUB9Qhcyd1zIcqn2uE8w9GFB445yCY46NOQO3ByaNyktX1DK+Etz7ZaX+w==", - "dev": true - }, - "node_modules/@types/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==", - "dev": true - }, - "node_modules/@types/d3-drag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.1.tgz", - "integrity": "sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==", - "dev": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-dsv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.0.tgz", - "integrity": "sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==", - "dev": true - }, - "node_modules/@types/d3-ease": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", - "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", - "dev": true - }, - "node_modules/@types/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==", - "dev": true, - "dependencies": { - "@types/d3-dsv": "*" - } - }, - "node_modules/@types/d3-force": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.3.tgz", - "integrity": "sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==", - "dev": true - }, - "node_modules/@types/d3-format": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz", - "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==", - "dev": true - }, - "node_modules/@types/d3-geo": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.2.tgz", - "integrity": "sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==", - "dev": true, - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-hierarchy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.0.2.tgz", - "integrity": "sha512-+krnrWOZ+aQB6v+E+jEkmkAx9HvsNAD+1LCD0vlBY3t+HwjKnsBFbpVLx6WWzDzCIuiTWdAxXMEnGnVXpB09qQ==", - "dev": true - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", - "dev": true, - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", - "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==", - "dev": true - }, - "node_modules/@types/d3-polygon": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.0.tgz", - "integrity": "sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==", - "dev": true - }, - "node_modules/@types/d3-quadtree": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz", - "integrity": "sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==", - "dev": true - }, - "node_modules/@types/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==", - "dev": true - }, - "node_modules/@types/d3-scale": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.1.tgz", - "integrity": "sha512-GDuXcRcR6mKcpUVMhPNttpOzHi2dP6YcDqLZYSZHgwTZ+sfCa8e9q0VEBwZomblAPNMYpVqxojnSyIEb4s/Pwg==", - "dev": true, - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==", - "dev": true - }, - "node_modules/@types/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-SZsDWFG1dLV9ivX2wGDPFWgLUf71tF4aupfEMTYMrbArHwEMLhmv3TS1CZECLQgoTttdpM1g5Z6JwRP7zoInWg==", - "dev": true - }, - "node_modules/@types/d3-shape": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.0.2.tgz", - "integrity": "sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==", - "dev": true, - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==", - "dev": true - }, - "node_modules/@types/d3-time-format": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.0.tgz", - "integrity": "sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==", - "dev": true - }, - "node_modules/@types/d3-timer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", - "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==", - "dev": true - }, - "node_modules/@types/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==", - "dev": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-zoom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.1.tgz", - "integrity": "sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==", - "dev": true, - "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, "node_modules/@types/dom4": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.2.tgz", @@ -4259,16 +3932,6 @@ "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", "dev": true }, - "node_modules/@types/expect-puppeteer": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@types/expect-puppeteer/-/expect-puppeteer-4.4.6.tgz", - "integrity": "sha512-RgQND/7RvcJm4NL2qoQbvVHTcfDh3h3yYe0Em0roczXY+MOIBkcgv5WRzVKeQJKO1nyhc4bEAbxpwykjDUMdqg==", - "dev": true, - "dependencies": { - "@types/jest": "*", - "@types/puppeteer": "*" - } - }, "node_modules/@types/favicons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/@types/favicons/-/favicons-5.5.0.tgz", @@ -4278,18 +3941,6 @@ "@types/node": "*" } }, - "node_modules/@types/flatbuffers": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", - "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==", - "dev": true - }, - "node_modules/@types/geojson": { - "version": "7946.0.8", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", - "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", - "dev": true - }, "node_modules/@types/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", @@ -4324,12 +3975,6 @@ "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", "dev": true }, - "node_modules/@types/is-number": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@types/is-number/-/is-number-7.0.1.tgz", - "integrity": "sha512-X8x3GugC4+84FEukgkKT75SkSVdzdeZJzy5k7n5CRB7/jk0PgeYwe2O5qRx7qOTnKkLNMVOP2d190R7VWzbzEw==", - "dev": true - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -4354,138 +3999,12 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/jest": { - "version": "26.0.24", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", - "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", - "dev": true, - "dependencies": { - "jest-diff": "^26.0.0", - "pretty-format": "^26.0.0" - } - }, - "node_modules/@types/jest-environment-puppeteer": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@types/jest-environment-puppeteer/-/jest-environment-puppeteer-4.4.1.tgz", - "integrity": "sha512-LiZTD6i63le6QMnxi7pJB0SFv/fWtss6VVEEDm/UaeowBgjduf8txyE//j3WEeDPxngTvioUjbzA7Rc6Wc3cBA==", - "dev": true, - "dependencies": { - "@jest/types": ">=24 <=26", - "@types/puppeteer": "*", - "jest-environment-node": ">=24 <=26" - } - }, "node_modules/@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, - "node_modules/@types/lodash": { - "version": "4.14.171", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.171.tgz", - "integrity": "sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg==", - "dev": true - }, - "node_modules/@types/lodash.clonedeep": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz", - "integrity": "sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.difference": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.difference/-/lodash.difference-4.5.6.tgz", - "integrity": "sha512-wXH53r+uoUCrKhmh7S5Gf6zo3vpsx/zH2R4pvkmDlmopmMTCROAUXDpPMXATGCWkCjE6ik3VZzZUxBgMjZho9Q==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.every": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.every/-/lodash.every-4.6.6.tgz", - "integrity": "sha512-eZC30bvV8GtmVUcMMhdAS+C2VgmkLMhnLyjTlf2lsPxhiquHfr/f0EnlX20l4xQWXG3B7H+OTSoWPqONyCeD2Q==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.filter": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.filter/-/lodash.filter-4.6.6.tgz", - "integrity": "sha512-K9oEglaInmu7pnQnZYdciNePpKe0W7O9yssnCza9mLjpq5N5Ju8RIMwTvp9tovb8V5yemxFTJqHzG+tIkAl1xw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.foreach": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.foreach/-/lodash.foreach-4.5.6.tgz", - "integrity": "sha512-A8+157A+27zwJSstmW/eWPc9lHLJNEer4jiMlsyxWieBxEx0arwB9vgQm+iai6DEDYYQuufHrzVhQOiapCalQQ==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.isnumber": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isnumber/-/lodash.isnumber-3.0.6.tgz", - "integrity": "sha512-nnfRqgijLFBEVu8W6pkHGq4hefaQOMcVwqeY19qIpf4qhV04mczNZvyT4Hc8UjOcnCIXErQG0aqIJedqlbbvVw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.map": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/@types/lodash.map/-/lodash.map-4.6.13.tgz", - "integrity": "sha512-kppRBzlpuvQQsr7R2nv/DDDZds8fglRFNAK70WUOkOC18KOcuQ22oQF9Kgy5Z2v/eDNkBm0ltrT6FThSkuWwow==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.pull": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/lodash.pull/-/lodash.pull-4.1.6.tgz", - "integrity": "sha512-pK+efqDL+Of68Gqd81LfOdBAmB5X6+SHM6kkUTTFQWqOPAomn3BWJcASLrr998SRE7aYLnDVmM5wLLbS7T159A==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.sortby": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/@types/lodash.sortby/-/lodash.sortby-4.7.6.tgz", - "integrity": "sha512-EnvAOmKvEg7gdYpYrS6+fVFPw5dL9rBnJi3vcKI7wqWQcLJVF/KRXK9dH29HjGNVvFUj0s9prRP3J8jEGnGKDw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.uniq": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", - "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/lodash.zip": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@types/lodash.zip/-/lodash.zip-4.2.6.tgz", - "integrity": "sha512-mKAcnkyFaihVR1oK83ZBQqSSQ1hpAY+uD5QaDkf//xtvr4NlNwqJEDg/oQoqLJg5YdSEwVWlQq0Aq4oLvD3zuw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -4493,9 +4012,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.7.tgz", - "integrity": "sha512-aDDY54sst8sx47CWT6QQqIZp45yURq4dic0+HCYfYNcY5Ejlb/CLmFnRLfy3wQuYafOeh3lB/DAKaqRKBtcZmA==", + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.2.tgz", + "integrity": "sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -4504,12 +4023,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "node_modules/@types/pako": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.2.tgz", - "integrity": "sha512-8UJl2MjkqqS6ncpLZqRZ5LmGiFBkbYxocD4e4jmBqGvfRG1RS23gKsBQbdtV9O9GvRyjFTiRHRByjSlKCLlmZw==", - "dev": true - }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -4527,15 +4040,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" }, - "node_modules/@types/puppeteer": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.4.tgz", - "integrity": "sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -4543,33 +4047,15 @@ "dev": true }, "node_modules/@types/react": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz", - "integrity": "sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw==", + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.19.tgz", + "integrity": "sha512-sX1HisdB1/ZESixMTGnMxH9TDe8Sk709734fEQZzCV/4lSu9kJCPbo2PbTRoZM+53Pp0P10hYVyReUueGwUi4A==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, - "node_modules/@types/react-dom": { - "version": "17.0.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz", - "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-helmet": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.2.tgz", - "integrity": "sha512-dcfAZNlWb5JYFbO9CGfrPWLJAyFcT6UeR3u35eBbv8liY2Rg4K7fM1G5+HnwVgot+C+kVwXAZ8pLEn2jsMfTDg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-redux": { "version": "7.1.18", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz", @@ -4586,15 +4072,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, - "node_modules/@types/sha1": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/sha1/-/sha1-1.1.3.tgz", - "integrity": "sha512-bXfx/6xrPu1l6pLItGRMPX00lhnJavpj2qiQeLHflXvL2Ix97aC8FTF2/pQoqukRzcCwKyN3csZvOLzamIoaSA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -4626,62 +4103,16 @@ "@types/node": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz", - "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.28.5", - "@typescript-eslint/scope-manager": "4.28.5", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", - "integrity": "sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.2.tgz", + "integrity": "sha512-P6mn4pqObhftBBPAv4GQtEK7Yos1fz/MlpT7+YjH9fTxZcALbiiPKuSIfYP/j13CeOjfq8/fr9Thr2glM9ub7A==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", + "@typescript-eslint/scope-manager": "4.29.2", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/typescript-estree": "4.29.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -4696,41 +4127,14 @@ "eslint": "*" } }, - "node_modules/@typescript-eslint/parser": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", - "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", - "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.2.tgz", + "integrity": "sha512-mfHmvlQxmfkU8D55CkZO2sQOueTxLqGvzV+mG6S/6fIunDiD2ouwsAoiYCZYDDK73QCibYjIZmGhpvKwAB5BOA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4741,9 +4145,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", - "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.2.tgz", + "integrity": "sha512-K6ApnEXId+WTGxqnda8z4LhNMa/pZmbTFkDxEBLQAbhLZL50DjeY0VIDCml/0Y3FlcbqXZrABqrcKxq+n0LwzQ==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4754,13 +4158,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", - "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.2.tgz", + "integrity": "sha512-TJ0/hEnYxapYn9SGn3dCnETO0r+MjaxtlWZ2xU+EvytF0g4CqTpZL48SqSNn2hXsPolnewF30pdzR9a5Lj3DNg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -4796,12 +4200,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", - "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.2.tgz", + "integrity": "sha512-bDgJLQ86oWHJoZ1ai4TZdgXzJxsea3Ee9u9wsTAvjChdj2WLcVsgWYAPeY7RQMn16tKrlQaBnpKv7KBfs4EQag==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.2", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -4981,9 +4385,9 @@ } }, "node_modules/@webpack-cli/serve": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.1.tgz", - "integrity": "sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", + "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", "dev": true, "peerDependencies": { "webpack-cli": "4.x.x" @@ -5058,6 +4462,15 @@ "acorn-walk": "^7.1.1" } }, + "node_modules/acorn-import-assertions": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", + "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -5101,15 +4514,6 @@ "node": ">=8" } }, - "node_modules/aggregate-error/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5406,12 +4810,12 @@ } }, "node_modules/ast-metadata-inferer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.5.1.tgz", - "integrity": "sha512-fj+QuB47ODy18p5gJ4BFnpenk992o7gx7oPid6oUK9+Uy/F3/5cvZ13harpQPN5Y8MlcjYf0y1LwgOV1J31k+A==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz", + "integrity": "sha512-OkMLzd8xelb3gmnp6ToFvvsHLtS6CbagTkFQvQ+ZYFe3/AIl9iKikNR9G7pY3GfOR/2Xc222hwBjzI7HLkE76Q==", "dev": true, "dependencies": { - "@mdn/browser-compat-data": "^3.3.11" + "@mdn/browser-compat-data": "^3.3.14" } }, "node_modules/ast-types-flow": { @@ -5940,16 +5344,16 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "node-releases": "^1.1.75" }, "bin": { "browserslist": "cli.js" @@ -6156,9 +5560,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001248", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001248.tgz", - "integrity": "sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==", + "version": "1.0.30001251", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", + "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", "dev": true, "funding": { "type": "opencollective", @@ -6384,9 +5788,9 @@ "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" }, "node_modules/clean-css": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.4.tgz", - "integrity": "sha512-e6JAuR0T2ahg7fOSv98Nxqh7mHWOac5TaCSgrr61h/6mkPLwlxX38hzob4h6IKj/UHlrrLXvAEjWqXlvi8r8lQ==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.5.tgz", + "integrity": "sha512-9dr/cU/LjMpU57PXlSvDkVRh0rPxJBXiBtD0+SgYt8ahTCsXtfKjCkNYgIoTC6mBg8CFr5EKhW3DKCaGMUbUfQ==", "dev": true, "dependencies": { "source-map": "~0.6.0" @@ -6726,9 +6130,9 @@ "dev": true }, "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "node_modules/colors": { @@ -6848,9 +6252,9 @@ } }, "node_modules/core-js": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz", - "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.2.tgz", + "integrity": "sha512-P0KPukO6OjMpjBtHSceAZEWlDD1M2Cpzpg6dBbrjFqFhBHe/BwhxaP820xKOjRn/lZRQirrCusIpLS/n2sgXLQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -6858,12 +6262,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.0.tgz", - "integrity": "sha512-5D9sPHCdewoUK7pSUPfTF7ZhLh8k9/CoJXWUEo+F1dZT5Z1DVgcuRqUKhjeKW+YLb8f21rTFgWwQJiNw1hoZ5Q==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.2.tgz", + "integrity": "sha512-4lUshXtBXsdmp8cDWh6KKiHUg40AjiuPD3bOWkNVsr1xkAhpUqCjaZ8lB1bKx9Gb5fXcbRbFJ4f4qpRIRTuJqQ==", "dev": true, "dependencies": { - "browserslist": "^4.16.6", + "browserslist": "^4.16.7", "semver": "7.0.0" }, "funding": { @@ -6881,9 +6285,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.0.tgz", - "integrity": "sha512-wzlhZNepF/QA9yvx3ePDgNGudU5KDB8lu/TRPKelYA/QtSnkS/cLl2W+TIdEX1FAFcBr0YpY7tPDlcmXJ7AyiQ==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.2.tgz", + "integrity": "sha512-oxKe64UH049mJqrKkynWp6Vu0Rlm/BTXO/bJZuN2mmR3RtOFNepLlSWDd1eo16PzHpQAoNG97rLU1V/YxesJjw==", "dev": true, "hasInstallScript": true, "funding": { @@ -8477,6 +7881,27 @@ "tslib": "^2.0.3" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -8494,9 +7919,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.791", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.791.tgz", - "integrity": "sha512-Tdx7w1fZpeWOOBluK+kXTAKCXyc79K65RB6Zp0+sPSZZhDjXlrxfGlXrlMGVVQUrKCyEZFQs1UBBLNz5IdbF0g==", + "version": "1.3.813", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.813.tgz", + "integrity": "sha512-YcSRImHt6JZZ2sSuQ4Bzajtk98igQ0iKkksqlzZLzbh4p0OIyJRSvUbsgqfcR8txdfsoYCc4ym306t4p2kP/aw==", "dev": true }, "node_modules/emittery": { @@ -8599,9 +8024,9 @@ } }, "node_modules/es-abstract": { - "version": "1.18.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.4.tgz", - "integrity": "sha512-xjDAPJRxKc1uoTkdW8MEk7Fq/2bzz3YoCADYniDV7+KITCUdu9c90fj1aKI7nEZFZxRrHlDo3wtma/C6QkhlXQ==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", @@ -8652,6 +8077,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -8772,9 +8203,9 @@ } }, "node_modules/eslint": { - "version": "7.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", - "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", @@ -8867,17 +8298,6 @@ "eslint-plugin-import": "^2.22.1" } }, - "node_modules/eslint-config-airbnb-typescript": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz", - "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==", - "dev": true, - "dependencies": { - "@typescript-eslint/parser": "^4.4.1", - "eslint-config-airbnb": "^18.2.0", - "eslint-config-airbnb-base": "^14.2.0" - } - }, "node_modules/eslint-config-prettier": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", @@ -8891,30 +8311,24 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/eslint-loader": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-4.0.2.tgz", @@ -8995,9 +8409,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "dependencies": { "debug": "^3.2.7", @@ -9017,16 +8431,16 @@ } }, "node_modules/eslint-plugin-compat": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.11.1.tgz", - "integrity": "sha512-iJyltnaVN9g/MYL3WGb6GFyJs+4mMkumq2E5srxsQIfPqQh14HEE0dtQC/HKDWze+hkwQtSo5DvC3IW5Gmxdtw==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.13.0.tgz", + "integrity": "sha512-cv8IYMuTXm7PIjMVDN2y4k/KVnKZmoNGHNq27/9dLstOLydKblieIv+oe2BN2WthuXnFNhaNvv3N1Bvl4dbIGA==", "dev": true, "dependencies": { - "@mdn/browser-compat-data": "^3.3.11", - "ast-metadata-inferer": "^0.5.1", - "browserslist": "^4.16.6", - "caniuse-lite": "^1.0.30001245", - "core-js": "^3.15.2", + "@mdn/browser-compat-data": "^3.3.14", + "ast-metadata-inferer": "^0.7.0", + "browserslist": "^4.16.8", + "caniuse-lite": "^1.0.30001251", + "core-js": "^3.16.2", "find-up": "^5.0.0", "lodash.memoize": "4.1.2", "semver": "7.3.5" @@ -9167,26 +8581,26 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "version": "2.24.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz", + "integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==", "dev": true, "dependencies": { "array-includes": "^3.1.3", "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.6.2", "find-up": "^2.0.0", "has": "^1.0.3", - "is-core-module": "^2.4.0", + "is-core-module": "^2.6.0", "minimatch": "^3.0.4", - "object.values": "^1.1.3", + "object.values": "^1.1.4", "pkg-up": "^2.0.0", "read-pkg-up": "^3.0.0", "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" + "tsconfig-paths": "^3.10.1" }, "engines": { "node": ">=4" @@ -9472,9 +8886,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -10078,9 +9492,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", - "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -10459,9 +9873,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", + "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", "dev": true, "funding": [ { @@ -10923,9 +10337,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, "node_modules/growly": { @@ -11003,6 +10417,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -11095,6 +10523,11 @@ "react-is": "^16.7.0" } }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -11553,6 +10986,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -11644,11 +11086,12 @@ } }, "node_modules/is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11664,21 +11107,25 @@ "dev": true }, "node_modules/is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11694,9 +11141,9 @@ "dev": true }, "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true, "engines": { "node": ">= 0.4" @@ -11732,9 +11179,9 @@ } }, "node_modules/is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -11756,9 +11203,12 @@ } }, "node_modules/is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -11880,10 +11330,13 @@ } }, "node_modules/is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -11952,12 +11405,12 @@ "dev": true }, "node_modules/is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11994,10 +11447,13 @@ } }, "node_modules/is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -12587,12 +12043,6 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-environment-puppeteer/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/jest-fetch-mock": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", @@ -13070,9 +12520,9 @@ } }, "node_modules/joi": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.1.tgz", - "integrity": "sha512-gDPOwQ5sr+BUxXuPDGrC1pSNcVR/yGGcTI0aCnjYxZEa3za60K/iCQ+OFIkEHWZGVCUcUlXlFKvMmrlmxrG6UQ==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", "dev": true, "dependencies": { "@hapi/hoek": "^9.0.0", @@ -13113,9 +12563,9 @@ "dev": true }, "node_modules/jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "dependencies": { "abab": "^2.0.5", @@ -13143,7 +12593,7 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.5", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, "engines": { @@ -14213,9 +13663,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -14378,9 +13828,9 @@ } }, "node_modules/node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", "dev": true }, "node_modules/normalize-package-data": { @@ -14982,9 +14432,9 @@ } }, "node_modules/parse-headers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", - "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", + "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", "dev": true }, "node_modules/parse-json": { @@ -16491,18 +15941,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "node_modules/postcss-merge-rules/node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss-merge-rules/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -16521,15 +15959,6 @@ "node": ">=4" } }, - "node_modules/postcss-merge-rules/node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss-merge-rules/node_modules/postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -17044,18 +16473,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "node_modules/postcss-minify-selectors/node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss-minify-selectors/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -17074,15 +16491,6 @@ "node": ">=4" } }, - "node_modules/postcss-minify-selectors/node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss-minify-selectors/node_modules/postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -19019,9 +18427,9 @@ "dev": true }, "node_modules/prebuild-install": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.3.tgz", - "integrity": "sha512-iqqSR84tNYQUQHRXalSKdIaM8Ov1QxOVuBNWI7+BzZWv6Ih9k75wOnH1rGQ9WWTaaLkTpxWKIciOF0KyfM74+Q==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "dev": true, "dependencies": { "detect-libc": "^1.0.3", @@ -19091,12 +18499,6 @@ "node": ">= 10" } }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -19150,6 +18552,11 @@ "react-is": "^16.8.1" } }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -19413,9 +18820,10 @@ } }, "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", @@ -19423,16 +18831,20 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "node_modules/react-popper": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", - "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", + "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", "dependencies": { - "react-fast-compare": "^3.0.1", + "@babel/runtime": "^7.1.2", + "@hypnosphi/create-react-context": "^0.3.1", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", "warning": "^4.0.2" }, "peerDependencies": { - "@popperjs/core": "^2.0.0", - "react": "^16.8.0 || ^17" + "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/react-redux": { @@ -19459,6 +18871,11 @@ } } }, + "node_modules/react-redux/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/react-side-effect": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", @@ -19634,9 +19051,9 @@ } }, "node_modules/redux": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", - "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.1.tgz", + "integrity": "sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw==", "dependencies": { "@babel/runtime": "^7.9.2" } @@ -19973,12 +19390,6 @@ "integrity": "sha1-WtAUcJnROp84qnuZrx1ueGZu038=", "dev": true }, - "node_modules/resize-img/node_modules/es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, "node_modules/resize-img/node_modules/file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", @@ -21229,9 +20640,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "node_modules/split-string": { @@ -21268,6 +20679,11 @@ "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, "engines": { "node": ">=0.10.0" } @@ -21668,18 +21084,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "node_modules/stylehacks/node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/stylehacks/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -21698,15 +21102,6 @@ "node": ">=4" } }, - "node_modules/stylehacks/node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/stylehacks/node_modules/postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -22474,9 +21869,9 @@ } }, "node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -22577,19 +21972,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -23122,9 +22504,9 @@ } }, "node_modules/webpack": { - "version": "5.47.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.47.1.tgz", - "integrity": "sha512-cW+Mzy9SCDapFV4OrkHuP6EFV2mAsiQd+gOa3PKtHNoKg6qPqQXZzBlHH+CnQG1osplBCqwsJZ8CfGO6XWah0g==", + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.1.tgz", + "integrity": "sha512-xsn3lwqEKoFvqn4JQggPSRxE4dhsRcysWTqYABAZlmavcoTmwlOb9b1N36Inbt/eIispSkuHa80/FJkDTPos1A==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.0", @@ -23133,6 +22515,7 @@ "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.8.0", @@ -23149,7 +22532,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.2.0", - "webpack-sources": "^3.1.1" + "webpack-sources": "^3.2.0" }, "bin": { "webpack": "bin/webpack.js" @@ -23168,15 +22551,15 @@ } }, "node_modules/webpack-cli": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.2.tgz", - "integrity": "sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.8.0.tgz", + "integrity": "sha512-+iBSWsX16uVna5aAYN6/wjhJy1q/GKk4KjKvfg90/6hykCTSgozbfz5iRgDTSJt/LgSbYxdBX3KBHeobIs+ZEw==", "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.0.4", "@webpack-cli/info": "^1.3.0", - "@webpack-cli/serve": "^1.5.1", + "@webpack-cli/serve": "^1.5.2", "colorette": "^1.2.1", "commander": "^7.0.0", "execa": "^5.0.0", @@ -23369,9 +22752,9 @@ } }, "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.1.2.tgz", - "integrity": "sha512-//DeuK5SzM6yFRXNOGK+4tX7QB8PghkL8kFBPyqSlN62oJOUkmby8ptV7+IBGH6BkIuIw5Rjd7OvvwZaoiF4ag==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", "dev": true, "engines": { "node": ">=10.13.0" @@ -23795,47 +23178,47 @@ } }, "@aws-sdk/abort-controller": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.23.0.tgz", - "integrity": "sha512-M69Sdoi6TH2UrnXKKNJNDaW6iCqpras7w274CZq4NjFOGwrb23KO2Aexgxr3g3hsUidfjuA38oFbHgC8odFrIQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.25.0.tgz", + "integrity": "sha512-uEVKqKkPVz6atbCxCNJY5O7V+ieSK8crUswXo8/WePyEbGEgxJ4t9x/WG4lV8kBjelmvQHDR4GqfJmb5Sh9xSg==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/client-secrets-manager": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.24.0.tgz", - "integrity": "sha512-zpu7XGlXlUnYqIeNiCH+mMmHLKyqIpIyi+lLGly0PYuPPmPOj0nB+X++H927maeoDHyKjfU+GP6863CypxhA0g==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.27.0.tgz", + "integrity": "sha512-WsVytEQKOjDKZKszm0Mfd3sCvUG1fYr2iu5yOnMaeAQQjCNw5nQ0tif0mC0suVG3847DvBJ9ajNab82EI5R1PQ==", "requires": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/client-sts": "3.24.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/credential-provider-node": "3.24.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/client-sts": "3.27.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/credential-provider-node": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "tslib": "^2.3.0", @@ -23843,73 +23226,73 @@ } }, "@aws-sdk/client-sso": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.24.0.tgz", - "integrity": "sha512-gee+zjIUiDayRhDsUakB/9h1crH419pgDWdZ91s/jXkOVXlCRoVaArmYPUBBWkVvGMoSvM6BVvojf2cWViA5FA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.27.0.tgz", + "integrity": "sha512-/Op+OaQgcAG/FyyqJc2NVfIJWEd1cTWIl8gBWSTUugrhhd5rMnAtg3u5ds/tYUimVQJv03z4bDjbI0Rnv/t6XQ==", "requires": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/client-sts": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.24.0.tgz", - "integrity": "sha512-GifVktvnDQlEJfspoERAFhS+vm7b0OmK3ACN/a6/wFc3hXEGIcS/WRzfRERXJfYg8Ial4Sr8bxDXMW30jPk3fQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.27.0.tgz", + "integrity": "sha512-QagsjULn6eacR/IL9d/nky17jUcqnbeShrHGrAyOhAXtehG3g2kkFcGbFy30iNw8gl1LteZL9dslpPFdWIEI1A==", "requires": { "@aws-crypto/sha256-browser": "^1.0.0", "@aws-crypto/sha256-js": "^1.0.0", - "@aws-sdk/config-resolver": "3.23.0", - "@aws-sdk/credential-provider-node": "3.24.0", - "@aws-sdk/fetch-http-handler": "3.23.0", - "@aws-sdk/hash-node": "3.23.0", - "@aws-sdk/invalid-dependency": "3.23.0", - "@aws-sdk/middleware-content-length": "3.23.0", - "@aws-sdk/middleware-host-header": "3.23.0", - "@aws-sdk/middleware-logger": "3.23.0", - "@aws-sdk/middleware-retry": "3.23.0", - "@aws-sdk/middleware-sdk-sts": "3.23.0", - "@aws-sdk/middleware-serde": "3.23.0", - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/middleware-user-agent": "3.23.0", - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/node-http-handler": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/smithy-client": "3.24.0", - "@aws-sdk/types": "3.22.0", - "@aws-sdk/url-parser": "3.23.0", + "@aws-sdk/config-resolver": "3.27.0", + "@aws-sdk/credential-provider-node": "3.27.0", + "@aws-sdk/fetch-http-handler": "3.25.0", + "@aws-sdk/hash-node": "3.25.0", + "@aws-sdk/invalid-dependency": "3.25.0", + "@aws-sdk/middleware-content-length": "3.25.0", + "@aws-sdk/middleware-host-header": "3.25.0", + "@aws-sdk/middleware-logger": "3.25.0", + "@aws-sdk/middleware-retry": "3.27.0", + "@aws-sdk/middleware-sdk-sts": "3.27.0", + "@aws-sdk/middleware-serde": "3.25.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/middleware-user-agent": "3.25.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/node-http-handler": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/smithy-client": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "@aws-sdk/util-base64-node": "3.23.0", "@aws-sdk/util-body-length-browser": "3.23.0", "@aws-sdk/util-body-length-node": "3.23.0", - "@aws-sdk/util-user-agent-browser": "3.23.0", - "@aws-sdk/util-user-agent-node": "3.23.0", + "@aws-sdk/util-user-agent-browser": "3.25.0", + "@aws-sdk/util-user-agent-node": "3.27.0", "@aws-sdk/util-utf8-browser": "3.23.0", "@aws-sdk/util-utf8-node": "3.23.0", "entities": "2.2.0", @@ -23918,132 +23301,134 @@ } }, "@aws-sdk/config-resolver": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.23.0.tgz", - "integrity": "sha512-acCxrAymwx81XELBO/d1VBWaHOldxqbmxDAMfvOfUYN+CYXWIFYpY1VCWuAeWig7Dy18QEJQ2pHwQlFxmilA7w==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.27.0.tgz", + "integrity": "sha512-gc7dfBzdmUHJamMjOc0bzAkIm3VUIK9kbLQSy0+nfjT641+AYvXO3qpjR6ywvutsbKhBg5kyGn/4QhyRxg61OQ==", "requires": { - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-env": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.23.0.tgz", - "integrity": "sha512-ljYkVATha4BdecVvYeW1WuzoAAwfM/i7p9Wmx1RY3Rb0AGwIFX2GjtoBPhS3EbCRTzQIhUr4zfIelVVVxIS6bA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.27.0.tgz", + "integrity": "sha512-IbPdlYl0A5GcpuT394cJceexxo0tzUzC7jIUxqL8gNbB/MIXC5ZlkeX9Z7bYloNb8SXk7GumXyQTsK1CchUvQA==", "requires": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-imds": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.23.0.tgz", - "integrity": "sha512-jD1EkoVDApKZJwOLACTrnxhDmQiVF1qMM+GMnoY4bMk1p1sfZYNKs6VkaY2LGUWXxkesj1aiMFxbwyWmu8SQbQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.27.0.tgz", + "integrity": "sha512-rhzlEvxiB7ecpVDl3NkjP1vPmqs+HHmqNXrK4efOYshwIbu+/h3xPePQMBOQ0AGezYn3k/iumoXXysVhVqtwUA==", "requires": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/url-parser": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-ini": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.24.0.tgz", - "integrity": "sha512-EwXEo0MqOjF28lIk1S2wo0HwIioUDC1LbFukd7mo3lIG47yS7Qllw7HIyhLzO5ayI5AouKP9nnLElgHVz81seg==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.27.0.tgz", + "integrity": "sha512-jvWUDz6nFqUvjmPRebwf1mWsOZ+inmZNQxz20DC/ROCRfGF1y8Yqf7KgCJy8MQOlDdTA4lPS+w6OJ0J/OOGbPg==", "requires": { - "@aws-sdk/credential-provider-env": "3.23.0", - "@aws-sdk/credential-provider-imds": "3.23.0", - "@aws-sdk/credential-provider-sso": "3.24.0", - "@aws-sdk/credential-provider-web-identity": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/credential-provider-env": "3.27.0", + "@aws-sdk/credential-provider-imds": "3.27.0", + "@aws-sdk/credential-provider-sso": "3.27.0", + "@aws-sdk/credential-provider-web-identity": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-node": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.24.0.tgz", - "integrity": "sha512-sQQDciLXYErBEIkphBlvIRh0shZe9iK6KqtpT5Sueu6ADEOIQlgF7Kw5/N9BhPQ8pYORibCH0eIabPD+u3hr9w==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.27.0.tgz", + "integrity": "sha512-GfCDX/AA7EJKyVGmNnh3wngWfEWFkuNJyend6FLN+81s3kUpXTkILuZCwQrD9AyjBYR2ksv0t929nW2fBUGT9Q==", "requires": { - "@aws-sdk/credential-provider-env": "3.23.0", - "@aws-sdk/credential-provider-imds": "3.23.0", - "@aws-sdk/credential-provider-ini": "3.24.0", - "@aws-sdk/credential-provider-process": "3.23.0", - "@aws-sdk/credential-provider-sso": "3.24.0", - "@aws-sdk/credential-provider-web-identity": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/credential-provider-env": "3.27.0", + "@aws-sdk/credential-provider-imds": "3.27.0", + "@aws-sdk/credential-provider-ini": "3.27.0", + "@aws-sdk/credential-provider-process": "3.27.0", + "@aws-sdk/credential-provider-sso": "3.27.0", + "@aws-sdk/credential-provider-web-identity": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-process": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.23.0.tgz", - "integrity": "sha512-xba0u86nS5MtH3FQKSbTOEaoHjqpoj6NyonZEy0O5i9KO0NHf+bZwlmI/pe54SOE9uSrDKHfXB6dsftVIqXtFQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.27.0.tgz", + "integrity": "sha512-F9pqKKnd5+fwoldVQJX9uLbDyPyIDnCpZGbiTw6BZANZM1qhjoEn7rNE5g2h0tkeq4dWMA9bANKMR4j3YhTpXw==", "requires": { - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-sso": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.24.0.tgz", - "integrity": "sha512-HZomNXn1kw/5M1AHFY7Rcnayl/7tXKG+67m7W3V9+G9+xzEjW5229y8VeZkoNUhVHh5rwvqd3fKKHx1g9sZsUA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.27.0.tgz", + "integrity": "sha512-yXyy+/FYFtpnRmPBiw5rxwSQBj1pcI0R+z77EA8a8+tozZPjsIri+xBsU62DtIlv/2yVb/goPgw+w2vg0L4NFw==", "requires": { - "@aws-sdk/client-sso": "3.24.0", - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/client-sso": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-credentials": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/credential-provider-web-identity": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.23.0.tgz", - "integrity": "sha512-GbDw2izWfb4KG62V6MBTOKmDAhbexbemxJsR0rMlZxW/dEYQh/r8Nk+m7evAUakNMJGm4fcAZGxey+orReq1VQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.27.0.tgz", + "integrity": "sha512-FYvDzB4UqmJjY+ZZoIAPM1EFK9/RdNn1VT5xvDcebQe7xKOVUG1tZbOA4rVZ3MUcxfyRqp7Ou/AhIWu/9RSt2Q==", "requires": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/fetch-http-handler": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.23.0.tgz", - "integrity": "sha512-gjToPkLlVOO8bHKhyw+d4mIX4OJEabqIFYbRFRDSm11LVLAAEc4pIFPYpMNWzrmDEnCxoGAcqfzP0m+0jChVCw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.25.0.tgz", + "integrity": "sha512-792kkbfSRBdiFb7Q2cDJts9MKxzAwuQSwUIwRKAOMazU8HkKbKnXXAFSsK3T7VasOFOh7O7YEGN0q9UgEw1q+g==", "requires": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/querystring-builder": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/querystring-builder": "3.25.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-base64-browser": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/hash-node": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.23.0.tgz", - "integrity": "sha512-yah+vNhKv6jpJR5qHYGc/AIAWwR9Ah9NplAq8cltMsPuI38u/aSlbcEIDwsRz3V1MDA89f/+qY3OHBfQw5kLVw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.25.0.tgz", + "integrity": "sha512-qRn6iqG9VLt8D29SBABcbauDLn92ssMjtpyVApiOhDYyFm2VA2avomOHD6y2PRBMwM5FMQAygZbpA2HIN2F96w==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-buffer-from": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/invalid-dependency": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.23.0.tgz", - "integrity": "sha512-5VqL7crIEtXj+lBwh3kKdMMlejjumjJQ5uLYNSCE/jNS5YjnbhAfO+fyzMO50IhcSuG4Ev6i1DEezN9BmYdeXA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.25.0.tgz", + "integrity": "sha512-ZBXjBAF2JSiO/wGBa1oaXsd1q5YG3diS8TfIUMXeQoe9O66R5LGoGOQeAbB/JjlwFot6DZfAcfocvl6CtWwqkw==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, @@ -24056,162 +23441,162 @@ } }, "@aws-sdk/middleware-content-length": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.23.0.tgz", - "integrity": "sha512-ooyNeXZUtI16Qh/HfcwLWn7NB2HvM/XEajaQmVIJXbVy/D2+N82+0Jo2hY3DouuIJjoEv/KZ5Uia/cgCdfHrHQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.25.0.tgz", + "integrity": "sha512-uOXus0MmZi/mucRIr5yfwM1vDhYG66CujNfnhyEaq5f4kcDA1Q5qPWSn9dkQPV9JWTZK3WTuYiOPSgtmlAYTAg==", "requires": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-host-header": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.23.0.tgz", - "integrity": "sha512-bHqQbwY3guUr+AWcrerHIh1ONgqhV8W85+H7MYlt0V5/Kom0+ectR7yZZRt90PDMZ8OsW4+f5jTIURFMLtPbDA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.25.0.tgz", + "integrity": "sha512-xKD/CfsUS3ul2VaQ3IgIUXgA7jU2/Guo/DUhYKrLZTOxm0nuvsIFw0RqSCtRBCLptE5Qi+unkc1LcFDbfqrRbg==", "requires": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-logger": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.23.0.tgz", - "integrity": "sha512-0z0ULcxllHO6xz1VeX/ekmg/LpNFL8nFbRH067s2KaimBeCUZ0CA2RwTpi9IY74tikmZAjerASb8eMgI+L/d7A==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.25.0.tgz", + "integrity": "sha512-M1F7BlAsDKoEM8hBaU2pHlLSM40rzzgtZ6jFNhfmTwGcjxe1N7JXCH5QPa7aI8wnJq2RoIRHVfVsUH4GwvOZnA==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-retry": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.23.0.tgz", - "integrity": "sha512-NimiKrP90+aW62QmkOrhQAZjrwjOQuWye2POzdetSrBHpnwj2KQWNBjcRwjkGt53krPcDyCySjIw+ivTRYdxWw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.27.0.tgz", + "integrity": "sha512-H57NP27qOxgbPRwCFkBYtAJylhAOWKSv3/TsCpDNnrb3Z0pqKUQH9mLC8hRGTRplkA7SDGfiuf9bsoNhZ3HFwQ==", "requires": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/service-error-classification": "3.22.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/service-error-classification": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0", "uuid": "^8.3.2" } }, "@aws-sdk/middleware-sdk-sts": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.23.0.tgz", - "integrity": "sha512-Rufzuqp4neVsyll9Ya9j+zpoK1fXrujBX6XRR5fRU3SsoAh5YWiUMrkxYxzTN+TLeXmyhCzmH/RuX2hgjMK0VQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.27.0.tgz", + "integrity": "sha512-4geCMczCujTz4GWSrwKhxEW9rYikp5NrLcIpHI0NjthQQfa8T4/D1WSsSnW3JNmQcMgQXeC9h8jTn0dOE4EhUw==", "requires": { - "@aws-sdk/middleware-signing": "3.23.0", - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/middleware-signing": "3.27.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-serde": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.23.0.tgz", - "integrity": "sha512-gNNMOo6Phm/BAnLsXvFfu4PHxKzN1saT3lNkODY2qKB1b4IoFNdMfHMo3jH4sbx7QYoM81qMXKr7aLp1BzTHtw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.25.0.tgz", + "integrity": "sha512-065Kugo8yXzBkcVAxctxFCHKlHcINnaQRsJ8ifvgc+UOEgvTG9+LfGWDwfdgarW9CkF7RkCoZOyaqFsO+HJWsg==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-signing": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.23.0.tgz", - "integrity": "sha512-cTozWnc8HLxLjHYU10+uqE4RqXYmmCJqoEKiSzJH7f8n20Pr9ly3rv3/9AfbqPth1PXsg0xHYq/ovCvq6RiaYA==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.27.0.tgz", + "integrity": "sha512-eOXwKOFuCIGAW3wZO9Cyh+z7swZYTq8BiBDjwWu6u0UBb5B/zMiq1z1LDa88iZY200O3Zip8+6RZV7LLd3XH+Q==", "requires": { - "@aws-sdk/property-provider": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/signature-v4": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/property-provider": "3.27.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/signature-v4": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/middleware-stack": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.23.0.tgz", - "integrity": "sha512-lk4u8wDajJ+VBXVWpzqaRUUJibt1YxsIciwLeZymilAZW5L9VtchUW9fmRpaZX8QHFGGkGuwZjtxlX6MeGXK4w==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.25.0.tgz", + "integrity": "sha512-s2VgdsasOVKHY3/SIGsw9AeZMMsdcIbBGWim9n5IO3j8C8y54EdRLVCEja8ePvMDZKIzuummwatYPHaUrnqPtQ==", "requires": { "tslib": "^2.3.0" } }, "@aws-sdk/middleware-user-agent": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.23.0.tgz", - "integrity": "sha512-cwOypi0no2Nsrw1N3VGe/0XgbNl487Wn4jgKZvj+nxdSWh4HQMWpoTLB3YZtzro+J7uVK6X7W+QxBU20+Ypg1g==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.25.0.tgz", + "integrity": "sha512-HXd/Qknq8Cp7fzJYU7jDDpN7ReJ3arUrnt+dAPNaDDrhmrBbCZp+24UXN6X6DAj0JICRoRuF/l7KxjwdF5FShw==", "requires": { - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/node-config-provider": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.23.0.tgz", - "integrity": "sha512-OyhyqTXUy5HxPu2c1aCYFHKQGjf4uzjby9AteMhRJfa6cehuVODi3KEv7PyZmJQcYI0Pw9ZnoHqVrTNsUEC2YQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.27.0.tgz", + "integrity": "sha512-5jeCLV7NI/ouQCMGDnGbxpCBhGirksXY55uvAaeysMxzjJLmPDwOZUD1gMhfYe8lxvktwhAndOdPQofWwTFUoQ==", "requires": { - "@aws-sdk/property-provider": "3.23.0", + "@aws-sdk/property-provider": "3.27.0", "@aws-sdk/shared-ini-file-loader": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/node-http-handler": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.23.0.tgz", - "integrity": "sha512-amvf0lwldUrr+CFtIeMZoNVmv34Fx3zwqobT5WuxtfRWbvSRALMw0LW/oXwoT+4WayM6sIwcIwSG1ZVGCjD0fA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.25.0.tgz", + "integrity": "sha512-zVeAM/bXewZiuMtcUZI/xGDID6knkzOv73ueVkzUbP0Ki8bfao7diR3hMbIt5Fy/r8cAVjJce9v6zFqo4sr1WA==", "requires": { - "@aws-sdk/abort-controller": "3.23.0", - "@aws-sdk/protocol-http": "3.23.0", - "@aws-sdk/querystring-builder": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/abort-controller": "3.25.0", + "@aws-sdk/protocol-http": "3.25.0", + "@aws-sdk/querystring-builder": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/property-provider": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.23.0.tgz", - "integrity": "sha512-GjFtmFHVzO4BeLRselGirt32cyorP1aRbD+ID4Zhz4RLxa9Nun766s8lqp7EcR/v9pSGdP1Xec3no8ALV3lXmw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.27.0.tgz", + "integrity": "sha512-8vovVNldgJwCpUfehdwUPwvzfUPB7TEW/tcTgrkLQW/cpEULbRrymtiZrzSkBLspNw2iU5d3FpQxE61s1ou0UA==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/protocol-http": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.23.0.tgz", - "integrity": "sha512-JTsq/UU/wTyeCMPVar2xSsMVFf72IK0L7dXbbS7ZHcBV6JAfM/wVTym8/s3mQGM6Kx/c6Wtn+J/5syDx56CV2g==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.25.0.tgz", + "integrity": "sha512-4Jebt5G8uIFa+HZO7KOgOtA66E/CXysQekiV5dfAsU8ca+rX5PB6qhpWZ2unX/l6He+oDQ0zMoW70JkNiP4/4w==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/querystring-builder": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.23.0.tgz", - "integrity": "sha512-MfQknhgMT9tul0VrxmLBDKlV7Ls2/kEJyprWXUWzCUBMUZ6M+FtOMJhjP90qTbsNvlsEVQgTlS/cDsNVrAUR3A==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.25.0.tgz", + "integrity": "sha512-o/R3/viOxjWckI+kepkxJSL7fIdg1hHYOW/rOpo9HbXS0CJrHVnB8vlBb+Xwl1IFyY2gg+5YZTjiufcgpgRBkw==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-uri-escape": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/querystring-parser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.23.0.tgz", - "integrity": "sha512-pMEN+rE08QhixRfWEBuQwnOGuGiRjH5++mmyQTUIvEgKk/rnyAkUlrySv775jvrEQlCXH8yqMuHdutF8rHkHGA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.25.0.tgz", + "integrity": "sha512-FCNyaOLFLVS5j43MhVA7/VJUDX0t/9RyNTNulHgzFjj6ffsgqcY0uwUq1RO3QCL4asl56zOrLVJgK+Z7wMbvFg==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/service-error-classification": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.22.0.tgz", - "integrity": "sha512-6ytFFoU8guAljwpmQTvZNf//cTurdumeLlAmQ8RJsbX3y5DGlpG2dfq7mpYJudtJtCQTwPYtaG5Xva460T2CqA==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.25.0.tgz", + "integrity": "sha512-66FfIab87LnnHtOLrGrVOht9Pw6lE8appyOpBdtoeoU5DP7ARSWuDdsYmKdGdRCWvn/RaVFbSYua9k0M1WsGqg==" }, "@aws-sdk/shared-ini-file-loader": { "version": "3.23.0", @@ -24222,39 +23607,39 @@ } }, "@aws-sdk/signature-v4": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.23.0.tgz", - "integrity": "sha512-3smgG/6LcK8SjVqWzroAgSFOF8HKp4/LtOQQBtPkI04nTMVP4zmE5hsVQEZv33h5UKWkUpwQRBTCtfFZTq/Jvw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.25.0.tgz", + "integrity": "sha512-6KDRRz9XVrj9RxrBLC6dzfnb2TDl3CjIzcNpLdRuKFgzEEdwV+5D+EZuAQU3MuHG5pWTIwG72k/dmCbJ2MDPUQ==", "requires": { "@aws-sdk/is-array-buffer": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "@aws-sdk/util-hex-encoding": "3.23.0", "@aws-sdk/util-uri-escape": "3.23.0", "tslib": "^2.3.0" } }, "@aws-sdk/smithy-client": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.24.0.tgz", - "integrity": "sha512-HFoRcO8eqnaN5+r5dPqP3t8ks0gBDhn0ClzTN8BloFwVVc0Wu7N1yZYp/NxLviwqC9X+R+ZbAJn+zjac24zgdw==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.27.0.tgz", + "integrity": "sha512-PpsSDUsRqw8HGuXv+AR2UzhVUJz4APM7K6Br8TTDPKvDwQtXkT5GROXRyAwU+htPcOHq006lS5EiF343y0HRvg==", "requires": { - "@aws-sdk/middleware-stack": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/middleware-stack": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, "@aws-sdk/types": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.22.0.tgz", - "integrity": "sha512-dGJBPbWm+YT+D5YIiqK3Z1xWzWShWgSxL1gPS9+vKNY2ld2TvtoiRhFy8NQG2jnC+eG/+WNeZS6ZxzLvEbQyTQ==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.25.0.tgz", + "integrity": "sha512-vS0+cTKwj6CujlR07HmeEBxzWPWSrdmZMYnxn/QC9KW9dFu0lsyCGSCqWsFluI6GI0flsnYYWNkP5y4bfD9tqg==" }, "@aws-sdk/url-parser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.23.0.tgz", - "integrity": "sha512-uU4BDX0eilGlMuz8qDlNzcH3k4WTZWgMnBuJ9+TdxTXNiLvC+X9HBjVmB2Nr+3mEJhhrRc/8mTrleJvcl60Pyg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.25.0.tgz", + "integrity": "sha512-qZ3Vq0NjHsE7Qq6R5NVRswIAsiyYjCDnAV+/Vt4jU/K0V3mGumiasiJyRyblW4Da8R6kfcJk0mHSMFRJfoHh8Q==", "requires": { - "@aws-sdk/querystring-parser": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/querystring-parser": "3.25.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, @@ -24334,22 +23719,22 @@ } }, "@aws-sdk/util-user-agent-browser": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.23.0.tgz", - "integrity": "sha512-FIjcCdvnUuOBMQgvPZ04Hk28Qy+xJDrtXeWm/7xKJ1K7NRucJWjmC+0OU0uw9A7VOCHf08nk9xniZhAGXs1wJg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.25.0.tgz", + "integrity": "sha512-qGqiWfs49NRmQVXPsBXgMRVkjDZocicU0V2wak98e0t7TOI+KmP8hnwsTkE6c4KwhsFOOUhAzjn5zk3kOwi6tQ==", "requires": { - "@aws-sdk/types": "3.22.0", + "@aws-sdk/types": "3.25.0", "bowser": "^2.11.0", "tslib": "^2.3.0" } }, "@aws-sdk/util-user-agent-node": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.23.0.tgz", - "integrity": "sha512-6okok4u13uYRIYdgFZ4dCsowf5vKh+ZxkfVSwvnZO3XAaGEhmIkM3+JKIQjcxLJ+Mt0ssMSJwNMz5oOBSlXPeQ==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.27.0.tgz", + "integrity": "sha512-jigZzAuhEnaLFeYEDGKQq8tas8OsT6qI7WAm/UnCXqtLhdnIu7u1yPhXk+TjI7SSn4Z6zP6Oh1qtFxzhpPmdoQ==", "requires": { - "@aws-sdk/node-config-provider": "3.23.0", - "@aws-sdk/types": "3.22.0", + "@aws-sdk/node-config-provider": "3.27.0", + "@aws-sdk/types": "3.25.0", "tslib": "^2.3.0" } }, @@ -24380,26 +23765,26 @@ } }, "@babel/compat-data": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", - "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", "dev": true }, "@babel/core": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz", - "integrity": "sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", + "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.8", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.8", + "@babel/generator": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", + "@babel/helper-module-transforms": "^7.15.0", "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.14.8", + "@babel/parser": "^7.15.0", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -24409,12 +23794,12 @@ } }, "@babel/generator": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", - "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", "dev": true, "requires": { - "@babel/types": "^7.14.8", + "@babel/types": "^7.15.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -24439,28 +23824,28 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", - "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", + "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", "browserslist": "^4.16.6", "semver": "^6.3.0" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.8.tgz", - "integrity": "sha512-bpYvH8zJBWzeqi1o+co8qOrw+EXzQ/0c74gVmY205AWXy9nifHrOg77y+1zwxX5lXE7Icq4sPlSQ4O2kWBrteQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", + "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.14.7", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-split-export-declaration": "^7.14.5" } }, @@ -24529,12 +23914,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", - "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", + "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.0" } }, "@babel/helper-module-imports": { @@ -24547,19 +23932,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz", - "integrity": "sha512-RyE+NFOjXn5A9YU1dkpeBaduagTlZ0+fccnIcAGbv1KGUlReBj7utF7oEth8IdIBQPcux0DDgW5MFBH2xu9KcA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-simple-access": "^7.14.8", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.8", + "@babel/helper-validator-identifier": "^7.14.9", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/helper-optimise-call-expression": { @@ -24589,15 +23974,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", - "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", + "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/helper-simple-access": { @@ -24628,9 +24013,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz", - "integrity": "sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", "dev": true }, "@babel/helper-validator-option": { @@ -24652,14 +24037,14 @@ } }, "@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", + "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", "dev": true, "requires": { "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/highlight": { @@ -24732,9 +24117,9 @@ } }, "@babel/parser": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.8.tgz", - "integrity": "sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", "dev": true }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { @@ -24749,9 +24134,9 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", - "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", + "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5", @@ -25098,15 +24483,6 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, - "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, "@babel/plugin-transform-arrow-functions": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", @@ -25137,18 +24513,18 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", - "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", + "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", - "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", + "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", @@ -25256,14 +24632,14 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", - "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", + "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-module-transforms": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-simple-access": "^7.14.8", "babel-plugin-dynamic-import-node": "^2.3.3" } }, @@ -25291,9 +24667,9 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", - "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", + "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" @@ -25346,25 +24722,25 @@ } }, "@babel/plugin-transform-react-display-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.5.tgz", - "integrity": "sha512-07aqY1ChoPgIxsuDviptRpVkWCSbXWmzQqcgy65C6YSFOfPFvb/DX3bBRHh7pCd/PMEEYHYWUTSVkCbkVainYQ==", + "version": "7.15.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", + "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.5.tgz", - "integrity": "sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", + "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-module-imports": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/types": "^7.14.9" } }, "@babel/plugin-transform-react-jsx-development": { @@ -25405,9 +24781,9 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", - "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz", + "integrity": "sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.14.5", @@ -25464,17 +24840,6 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, - "@babel/plugin-transform-typescript": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz", - "integrity": "sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.6", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" - } - }, "@babel/plugin-transform-unicode-escapes": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", @@ -25495,17 +24860,17 @@ } }, "@babel/preset-env": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.8.tgz", - "integrity": "sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", + "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.7", - "@babel/helper-compilation-targets": "^7.14.5", + "@babel/compat-data": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.7", + "@babel/plugin-proposal-async-generator-functions": "^7.14.9", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-class-static-block": "^7.14.5", "@babel/plugin-proposal-dynamic-import": "^7.14.5", @@ -25538,7 +24903,7 @@ "@babel/plugin-transform-async-to-generator": "^7.14.5", "@babel/plugin-transform-block-scoped-functions": "^7.14.5", "@babel/plugin-transform-block-scoping": "^7.14.5", - "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.9", "@babel/plugin-transform-computed-properties": "^7.14.5", "@babel/plugin-transform-destructuring": "^7.14.7", "@babel/plugin-transform-dotall-regex": "^7.14.5", @@ -25549,10 +24914,10 @@ "@babel/plugin-transform-literals": "^7.14.5", "@babel/plugin-transform-member-expression-literals": "^7.14.5", "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.15.0", "@babel/plugin-transform-modules-systemjs": "^7.14.5", "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", "@babel/plugin-transform-new-target": "^7.14.5", "@babel/plugin-transform-object-super": "^7.14.5", "@babel/plugin-transform-parameters": "^7.14.5", @@ -25567,11 +24932,11 @@ "@babel/plugin-transform-unicode-escapes": "^7.14.5", "@babel/plugin-transform-unicode-regex": "^7.14.5", "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.14.8", + "@babel/types": "^7.15.0", "babel-plugin-polyfill-corejs2": "^0.2.2", "babel-plugin-polyfill-corejs3": "^0.2.2", "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.15.0", + "core-js-compat": "^3.16.0", "semver": "^6.3.0" } }, @@ -25602,21 +24967,10 @@ "@babel/plugin-transform-react-pure-annotations": "^7.14.5" } }, - "@babel/preset-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz", - "integrity": "sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.14.5" - } - }, "@babel/register": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.14.5.tgz", - "integrity": "sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.15.3.tgz", + "integrity": "sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw==", "dev": true, "requires": { "clone-deep": "^4.0.1", @@ -25627,17 +24981,17 @@ } }, "@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", + "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs2": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.14.8.tgz", - "integrity": "sha512-Jj4fkQPFp73ia9y6BctEX5ypA1icbOVPtc9l0T1VnAv8EmzaN/Lm/WvnKNve1610VvHV69SLihpu9tHnVziBvw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.15.3.tgz", + "integrity": "sha512-iG7ypZmrdoKP1ckFurS8z97TR+Bqd6KaDsLQ9DiC/Rdxmrvy1nsCDlgfLNKfalbg9sFWdmIdNf+Hg+19XysSFg==", "dev": true, "requires": { "core-js": "^2.6.5", @@ -25653,12 +25007,12 @@ } }, "@babel/runtime-corejs3": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.8.tgz", - "integrity": "sha512-4dMD5QRBkumn45oweR0SxoNtt15oz3BUBAQ8cIx7HJqZTtE8zjpM0My8aHJHVnyf4XfRg6DNzaE1080WLBiC1w==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz", + "integrity": "sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==", "dev": true, "requires": { - "core-js-pure": "^3.15.0", + "core-js-pure": "^3.16.0", "regenerator-runtime": "^0.13.4" } }, @@ -25674,29 +25028,29 @@ } }, "@babel/traverse": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.8.tgz", - "integrity": "sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.8", + "@babel/generator": "^7.15.0", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.8", - "@babel/types": "^7.14.8", + "@babel/parser": "^7.15.0", + "@babel/types": "^7.15.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.8.tgz", - "integrity": "sha512-iob4soQa7dZw8nodR/KlOQkPh9S4I8RwCxwRIFuiMRYjOzH/KJzdUfDgz6cGi5dDaclXF4P2PAhCdrBJNIg68Q==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.8", + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, @@ -25706,12 +25060,18 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@blueprintjs/colors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/colors/-/colors-1.0.0.tgz", + "integrity": "sha512-eJh111ucz8HYxLBON6ADkAGQQBACqdbX6Zws/GpuiTkeCFJ3IAjZdBpk7IM7/Y5XuGuSS1ujwjnLDOEtyywtKw==" + }, "@blueprintjs/core": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.47.0.tgz", - "integrity": "sha512-u+bfmCyPXwKZMnwY4+e/iWjO2vDUvr8hA8ydmV0afyvcEe7Sh85UPEorIgQ/CBuRIbVMNm8FpLsFzDxgkfrCNA==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.48.0.tgz", + "integrity": "sha512-tuAL3dZrNaTq36RRy6O86wjmkiLt8LwHkleZ1zUcn/DC3cXsM3dSsRpV3f662bcEiAXMPeGemSC3tqv6uZCeLg==", "requires": { - "@blueprintjs/icons": "^3.27.0", + "@blueprintjs/colors": "^1.0.0", + "@blueprintjs/icons": "^3.28.0", "@types/dom4": "^2.0.1", "classnames": "^2.2", "dom4": "^2.1.5", @@ -25724,20 +25084,6 @@ "tslib": "~1.13.0" }, "dependencies": { - "react-popper": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", - "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", - "requires": { - "@babel/runtime": "^7.1.2", - "@hypnosphi/create-react-context": "^0.3.1", - "deep-equal": "^1.1.1", - "popper.js": "^1.14.4", - "prop-types": "^15.6.1", - "typed-styles": "^0.0.7", - "warning": "^4.0.2" - } - }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -25756,9 +25102,9 @@ } }, "@blueprintjs/icons": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.27.0.tgz", - "integrity": "sha512-ItRioyrr2s70chclj5q38HS9omKOa15b3JZXv9JcMIFz+6w6rAcoAH7DA+5xIs27bFjax/SdAZp/eYXSw0+QpA==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.28.0.tgz", + "integrity": "sha512-gDvvU2ljV4NXsY5ofKcs1ChXAgmqNp/DIMu2uJIJmXhSXfP6JDd4qbnbGMsP3FmLTaqQP3E9oBZqAG/FRB8VmQ==", "requires": { "classnames": "^2.2", "tslib": "~1.13.0" @@ -25784,6 +25130,15 @@ "tslib": "~1.13.0" }, "dependencies": { + "react-popper": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", + "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -25792,11 +25147,11 @@ } }, "@blueprintjs/select": { - "version": "3.16.6", - "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.16.6.tgz", - "integrity": "sha512-lg2duuzlRw18+pbET6vlRY/TVSuuSI6wI4DObUiBAfU7G3fMa6d10Sp+0Yn00XaMPQ5y3MGn1gz0EbIJ3/A5OA==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.17.0.tgz", + "integrity": "sha512-38jvSt1zGOJuw6Vj3BrDn1ojZCI+U5UV8xEupGPTEVyszE7RwFoF8l1iDTLbiPwLV5DSOxTN0B6mxeSPX45OQw==", "requires": { - "@blueprintjs/core": "^3.47.0", + "@blueprintjs/core": "^3.48.0", "classnames": "^2.2", "tslib": "~1.13.0" }, @@ -25842,9 +25197,9 @@ }, "dependencies": { "globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -26487,9 +25842,9 @@ } }, "@mdn/browser-compat-data": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.13.tgz", - "integrity": "sha512-YCclX4FGCVMkdIFykkyrgBkERN1huqU+Lyr767mbTuSVtj2LKfXpVwv/D0C1ZaefRvpinRJ/Xfy0mBNi7XIs0w==", + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.14.tgz", + "integrity": "sha512-n2RC9d6XatVbWFdHLimzzUJxJ1KY8LdjqrW6YvGPiRmsHkhOUx74/Ct10x5Yo7bC/Jvqx7cDEW8IMPv/+vwEzA==", "dev": true }, "@nodelib/fs.scandir": { @@ -26519,9 +25874,9 @@ } }, "@popperjs/core": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz", - "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==" + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz", + "integrity": "sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==" }, "@sentry/cli": { "version": "1.68.0", @@ -26538,12 +25893,12 @@ } }, "@sentry/webpack-plugin": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.16.0.tgz", - "integrity": "sha512-Ax0QZ3a+LFYU876Si2HElPYSj+mX3vinvzH+o9F1g/5T2Z3HqITnX6gg+zVfLFsE819PN9KeLpmoHtO352dlmQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.17.1.tgz", + "integrity": "sha512-L47a0hxano4a+9jbvQSBzHCT1Ph8fYAvGGUvFg8qc69yXS9si5lXRNIH/pavN6mqJjhQjAcEsEp+vxgvT4xZDQ==", "dev": true, "requires": { - "@sentry/cli": "^1.67.1" + "@sentry/cli": "^1.68.0" } }, "@sideway/address": { @@ -26632,259 +25987,6 @@ "@babel/types": "^7.3.0" } }, - "@types/d3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.0.0.tgz", - "integrity": "sha512-7rMMuS5unvbvFCJXAkQXIxWTo2OUlmVXN5q7sfQFesuVICY55PSP6hhbUhWjTTNpfTTB3iLALsIYDFe7KUNABw==", - "dev": true, - "requires": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" - } - }, - "@types/d3-array": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.1.tgz", - "integrity": "sha512-D/G7oG0czeszALrkdUiV68CDiHDxXf+M2mLVqAyKktGd12VKQQljj1sHJGBKjcK4jRH1biBd6ZPQPHpJ0mNa0w==", - "dev": true - }, - "@types/d3-axis": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.1.tgz", - "integrity": "sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-brush": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.1.tgz", - "integrity": "sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==", - "dev": true - }, - "@types/d3-color": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.0.2.tgz", - "integrity": "sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ==", - "dev": true - }, - "@types/d3-contour": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.1.tgz", - "integrity": "sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==", - "dev": true, - "requires": { - "@types/d3-array": "*", - "@types/geojson": "*" - } - }, - "@types/d3-delaunay": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.0.tgz", - "integrity": "sha512-iGm7ZaGLq11RK3e69VeMM6Oqj2SjKUB9Qhcyd1zIcqn2uE8w9GFB445yCY46NOQO3ByaNyktX1DK+Etz7ZaX+w==", - "dev": true - }, - "@types/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==", - "dev": true - }, - "@types/d3-drag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.1.tgz", - "integrity": "sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-dsv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.0.tgz", - "integrity": "sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==", - "dev": true - }, - "@types/d3-ease": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", - "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", - "dev": true - }, - "@types/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==", - "dev": true, - "requires": { - "@types/d3-dsv": "*" - } - }, - "@types/d3-force": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.3.tgz", - "integrity": "sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==", - "dev": true - }, - "@types/d3-format": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz", - "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==", - "dev": true - }, - "@types/d3-geo": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.2.tgz", - "integrity": "sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==", - "dev": true, - "requires": { - "@types/geojson": "*" - } - }, - "@types/d3-hierarchy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.0.2.tgz", - "integrity": "sha512-+krnrWOZ+aQB6v+E+jEkmkAx9HvsNAD+1LCD0vlBY3t+HwjKnsBFbpVLx6WWzDzCIuiTWdAxXMEnGnVXpB09qQ==", - "dev": true - }, - "@types/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", - "dev": true, - "requires": { - "@types/d3-color": "*" - } - }, - "@types/d3-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", - "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==", - "dev": true - }, - "@types/d3-polygon": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.0.tgz", - "integrity": "sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==", - "dev": true - }, - "@types/d3-quadtree": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz", - "integrity": "sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==", - "dev": true - }, - "@types/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==", - "dev": true - }, - "@types/d3-scale": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.1.tgz", - "integrity": "sha512-GDuXcRcR6mKcpUVMhPNttpOzHi2dP6YcDqLZYSZHgwTZ+sfCa8e9q0VEBwZomblAPNMYpVqxojnSyIEb4s/Pwg==", - "dev": true, - "requires": { - "@types/d3-time": "*" - } - }, - "@types/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==", - "dev": true - }, - "@types/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-SZsDWFG1dLV9ivX2wGDPFWgLUf71tF4aupfEMTYMrbArHwEMLhmv3TS1CZECLQgoTttdpM1g5Z6JwRP7zoInWg==", - "dev": true - }, - "@types/d3-shape": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.0.2.tgz", - "integrity": "sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==", - "dev": true, - "requires": { - "@types/d3-path": "*" - } - }, - "@types/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==", - "dev": true - }, - "@types/d3-time-format": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.0.tgz", - "integrity": "sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==", - "dev": true - }, - "@types/d3-timer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", - "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==", - "dev": true - }, - "@types/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-zoom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.1.tgz", - "integrity": "sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==", - "dev": true, - "requires": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, "@types/dom4": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.2.tgz", @@ -26916,16 +26018,6 @@ "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", "dev": true }, - "@types/expect-puppeteer": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@types/expect-puppeteer/-/expect-puppeteer-4.4.6.tgz", - "integrity": "sha512-RgQND/7RvcJm4NL2qoQbvVHTcfDh3h3yYe0Em0roczXY+MOIBkcgv5WRzVKeQJKO1nyhc4bEAbxpwykjDUMdqg==", - "dev": true, - "requires": { - "@types/jest": "*", - "@types/puppeteer": "*" - } - }, "@types/favicons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/@types/favicons/-/favicons-5.5.0.tgz", @@ -26935,18 +26027,6 @@ "@types/node": "*" } }, - "@types/flatbuffers": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", - "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==", - "dev": true - }, - "@types/geojson": { - "version": "7946.0.8", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", - "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", - "dev": true - }, "@types/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", @@ -26981,12 +26061,6 @@ "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", "dev": true }, - "@types/is-number": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@types/is-number/-/is-number-7.0.1.tgz", - "integrity": "sha512-X8x3GugC4+84FEukgkKT75SkSVdzdeZJzy5k7n5CRB7/jk0PgeYwe2O5qRx7qOTnKkLNMVOP2d190R7VWzbzEw==", - "dev": true - }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -27011,138 +26085,12 @@ "@types/istanbul-lib-report": "*" } }, - "@types/jest": { - "version": "26.0.24", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", - "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", - "dev": true, - "requires": { - "jest-diff": "^26.0.0", - "pretty-format": "^26.0.0" - } - }, - "@types/jest-environment-puppeteer": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@types/jest-environment-puppeteer/-/jest-environment-puppeteer-4.4.1.tgz", - "integrity": "sha512-LiZTD6i63le6QMnxi7pJB0SFv/fWtss6VVEEDm/UaeowBgjduf8txyE//j3WEeDPxngTvioUjbzA7Rc6Wc3cBA==", - "dev": true, - "requires": { - "@jest/types": ">=24 <=26", - "@types/puppeteer": "*", - "jest-environment-node": ">=24 <=26" - } - }, "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, - "@types/lodash": { - "version": "4.14.171", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.171.tgz", - "integrity": "sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg==", - "dev": true - }, - "@types/lodash.clonedeep": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz", - "integrity": "sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.difference": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.difference/-/lodash.difference-4.5.6.tgz", - "integrity": "sha512-wXH53r+uoUCrKhmh7S5Gf6zo3vpsx/zH2R4pvkmDlmopmMTCROAUXDpPMXATGCWkCjE6ik3VZzZUxBgMjZho9Q==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.every": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.every/-/lodash.every-4.6.6.tgz", - "integrity": "sha512-eZC30bvV8GtmVUcMMhdAS+C2VgmkLMhnLyjTlf2lsPxhiquHfr/f0EnlX20l4xQWXG3B7H+OTSoWPqONyCeD2Q==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.filter": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/@types/lodash.filter/-/lodash.filter-4.6.6.tgz", - "integrity": "sha512-K9oEglaInmu7pnQnZYdciNePpKe0W7O9yssnCza9mLjpq5N5Ju8RIMwTvp9tovb8V5yemxFTJqHzG+tIkAl1xw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.foreach": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.foreach/-/lodash.foreach-4.5.6.tgz", - "integrity": "sha512-A8+157A+27zwJSstmW/eWPc9lHLJNEer4jiMlsyxWieBxEx0arwB9vgQm+iai6DEDYYQuufHrzVhQOiapCalQQ==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.isnumber": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.isnumber/-/lodash.isnumber-3.0.6.tgz", - "integrity": "sha512-nnfRqgijLFBEVu8W6pkHGq4hefaQOMcVwqeY19qIpf4qhV04mczNZvyT4Hc8UjOcnCIXErQG0aqIJedqlbbvVw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.map": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/@types/lodash.map/-/lodash.map-4.6.13.tgz", - "integrity": "sha512-kppRBzlpuvQQsr7R2nv/DDDZds8fglRFNAK70WUOkOC18KOcuQ22oQF9Kgy5Z2v/eDNkBm0ltrT6FThSkuWwow==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.pull": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/lodash.pull/-/lodash.pull-4.1.6.tgz", - "integrity": "sha512-pK+efqDL+Of68Gqd81LfOdBAmB5X6+SHM6kkUTTFQWqOPAomn3BWJcASLrr998SRE7aYLnDVmM5wLLbS7T159A==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.sortby": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/@types/lodash.sortby/-/lodash.sortby-4.7.6.tgz", - "integrity": "sha512-EnvAOmKvEg7gdYpYrS6+fVFPw5dL9rBnJi3vcKI7wqWQcLJVF/KRXK9dH29HjGNVvFUj0s9prRP3J8jEGnGKDw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.uniq": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@types/lodash.uniq/-/lodash.uniq-4.5.6.tgz", - "integrity": "sha512-XHNMXBtiwsWZstZMyxOYjr0e8YYWv0RgPlzIHblTuwBBiWo2MzWVaTBihtBpslb5BglgAWIeBv69qt1+RTRW1A==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/lodash.zip": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@types/lodash.zip/-/lodash.zip-4.2.6.tgz", - "integrity": "sha512-mKAcnkyFaihVR1oK83ZBQqSSQ1hpAY+uD5QaDkf//xtvr4NlNwqJEDg/oQoqLJg5YdSEwVWlQq0Aq4oLvD3zuw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -27150,9 +26098,9 @@ "dev": true }, "@types/node": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.7.tgz", - "integrity": "sha512-aDDY54sst8sx47CWT6QQqIZp45yURq4dic0+HCYfYNcY5Ejlb/CLmFnRLfy3wQuYafOeh3lB/DAKaqRKBtcZmA==", + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.2.tgz", + "integrity": "sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA==", "dev": true }, "@types/normalize-package-data": { @@ -27161,12 +26109,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "@types/pako": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.2.tgz", - "integrity": "sha512-8UJl2MjkqqS6ncpLZqRZ5LmGiFBkbYxocD4e4jmBqGvfRG1RS23gKsBQbdtV9O9GvRyjFTiRHRByjSlKCLlmZw==", - "dev": true - }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -27184,15 +26126,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" }, - "@types/puppeteer": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.4.tgz", - "integrity": "sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -27200,33 +26133,15 @@ "dev": true }, "@types/react": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz", - "integrity": "sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw==", + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.19.tgz", + "integrity": "sha512-sX1HisdB1/ZESixMTGnMxH9TDe8Sk709734fEQZzCV/4lSu9kJCPbo2PbTRoZM+53Pp0P10hYVyReUueGwUi4A==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, - "@types/react-dom": { - "version": "17.0.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz", - "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-helmet": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.2.tgz", - "integrity": "sha512-dcfAZNlWb5JYFbO9CGfrPWLJAyFcT6UeR3u35eBbv8liY2Rg4K7fM1G5+HnwVgot+C+kVwXAZ8pLEn2jsMfTDg==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/react-redux": { "version": "7.1.18", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz", @@ -27243,15 +26158,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, - "@types/sha1": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/sha1/-/sha1-1.1.3.tgz", - "integrity": "sha512-bXfx/6xrPu1l6pLItGRMPX00lhnJavpj2qiQeLHflXvL2Ix97aC8FTF2/pQoqukRzcCwKyN3csZvOLzamIoaSA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -27283,82 +26189,44 @@ "@types/node": "*" } }, - "@typescript-eslint/eslint-plugin": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz", - "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.28.5", - "@typescript-eslint/scope-manager": "4.28.5", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, "@typescript-eslint/experimental-utils": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", - "integrity": "sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.2.tgz", + "integrity": "sha512-P6mn4pqObhftBBPAv4GQtEK7Yos1fz/MlpT7+YjH9fTxZcALbiiPKuSIfYP/j13CeOjfq8/fr9Thr2glM9ub7A==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", + "@typescript-eslint/scope-manager": "4.29.2", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/typescript-estree": "4.29.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, - "@typescript-eslint/parser": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", - "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", - "debug": "^4.3.1" - } - }, "@typescript-eslint/scope-manager": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", - "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.2.tgz", + "integrity": "sha512-mfHmvlQxmfkU8D55CkZO2sQOueTxLqGvzV+mG6S/6fIunDiD2ouwsAoiYCZYDDK73QCibYjIZmGhpvKwAB5BOA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2" } }, "@typescript-eslint/types": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", - "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.2.tgz", + "integrity": "sha512-K6ApnEXId+WTGxqnda8z4LhNMa/pZmbTFkDxEBLQAbhLZL50DjeY0VIDCml/0Y3FlcbqXZrABqrcKxq+n0LwzQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", - "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.2.tgz", + "integrity": "sha512-TJ0/hEnYxapYn9SGn3dCnETO0r+MjaxtlWZ2xU+EvytF0g4CqTpZL48SqSNn2hXsPolnewF30pdzR9a5Lj3DNg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -27378,12 +26246,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", - "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.2.tgz", + "integrity": "sha512-bDgJLQ86oWHJoZ1ai4TZdgXzJxsea3Ee9u9wsTAvjChdj2WLcVsgWYAPeY7RQMn16tKrlQaBnpKv7KBfs4EQag==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.2", "eslint-visitor-keys": "^2.0.0" } }, @@ -27537,8 +26405,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "1.3.0", @@ -27550,11 +26417,10 @@ } }, "@webpack-cli/serve": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.1.tgz", - "integrity": "sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw==", - "dev": true, - "requires": {} + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", + "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -27608,12 +26474,17 @@ "acorn-walk": "^7.1.1" } }, + "acorn-import-assertions": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", + "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", + "dev": true + }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -27638,14 +26509,6 @@ "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } } }, "ajv": { @@ -27664,8 +26527,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "alphanum-sort": { "version": "1.0.2", @@ -27866,12 +26728,12 @@ "dev": true }, "ast-metadata-inferer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.5.1.tgz", - "integrity": "sha512-fj+QuB47ODy18p5gJ4BFnpenk992o7gx7oPid6oUK9+Uy/F3/5cvZ13harpQPN5Y8MlcjYf0y1LwgOV1J31k+A==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz", + "integrity": "sha512-OkMLzd8xelb3gmnp6ToFvvsHLtS6CbagTkFQvQ+ZYFe3/AIl9iKikNR9G7pY3GfOR/2Xc222hwBjzI7HLkE76Q==", "dev": true, "requires": { - "@mdn/browser-compat-data": "^3.3.11" + "@mdn/browser-compat-data": "^3.3.14" } }, "ast-types-flow": { @@ -28289,16 +27151,16 @@ "dev": true }, "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "node-releases": "^1.1.75" } }, "bser": { @@ -28453,9 +27315,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001248", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001248.tgz", - "integrity": "sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==", + "version": "1.0.30001251", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", + "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", "dev": true }, "capture-exit": { @@ -28632,9 +27494,9 @@ "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" }, "clean-css": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.4.tgz", - "integrity": "sha512-e6JAuR0T2ahg7fOSv98Nxqh7mHWOac5TaCSgrr61h/6mkPLwlxX38hzob4h6IKj/UHlrrLXvAEjWqXlvi8r8lQ==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.5.tgz", + "integrity": "sha512-9dr/cU/LjMpU57PXlSvDkVRh0rPxJBXiBtD0+SgYt8ahTCsXtfKjCkNYgIoTC6mBg8CFr5EKhW3DKCaGMUbUfQ==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -28909,9 +27771,9 @@ } }, "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "colors": { @@ -29013,17 +27875,17 @@ "dev": true }, "core-js": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz", - "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==" + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.2.tgz", + "integrity": "sha512-P0KPukO6OjMpjBtHSceAZEWlDD1M2Cpzpg6dBbrjFqFhBHe/BwhxaP820xKOjRn/lZRQirrCusIpLS/n2sgXLQ==" }, "core-js-compat": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.0.tgz", - "integrity": "sha512-5D9sPHCdewoUK7pSUPfTF7ZhLh8k9/CoJXWUEo+F1dZT5Z1DVgcuRqUKhjeKW+YLb8f21rTFgWwQJiNw1hoZ5Q==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.2.tgz", + "integrity": "sha512-4lUshXtBXsdmp8cDWh6KKiHUg40AjiuPD3bOWkNVsr1xkAhpUqCjaZ8lB1bKx9Gb5fXcbRbFJ4f4qpRIRTuJqQ==", "dev": true, "requires": { - "browserslist": "^4.16.6", + "browserslist": "^4.16.7", "semver": "7.0.0" }, "dependencies": { @@ -29036,9 +27898,9 @@ } }, "core-js-pure": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.0.tgz", - "integrity": "sha512-wzlhZNepF/QA9yvx3ePDgNGudU5KDB8lu/TRPKelYA/QtSnkS/cLl2W+TIdEX1FAFcBr0YpY7tPDlcmXJ7AyiQ==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.2.tgz", + "integrity": "sha512-oxKe64UH049mJqrKkynWp6Vu0Rlm/BTXO/bJZuN2mmR3RtOFNepLlSWDd1eo16PzHpQAoNG97rLU1V/YxesJjw==", "dev": true }, "core-util-is": { @@ -30326,6 +29188,23 @@ "tslib": "^2.0.3" } }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + }, + "dependencies": { + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + } + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -30343,9 +29222,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.791", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.791.tgz", - "integrity": "sha512-Tdx7w1fZpeWOOBluK+kXTAKCXyc79K65RB6Zp0+sPSZZhDjXlrxfGlXrlMGVVQUrKCyEZFQs1UBBLNz5IdbF0g==", + "version": "1.3.813", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.813.tgz", + "integrity": "sha512-YcSRImHt6JZZ2sSuQ4Bzajtk98igQ0iKkksqlzZLzbh4p0OIyJRSvUbsgqfcR8txdfsoYCc4ym306t4p2kP/aw==", "dev": true }, "emittery": { @@ -30421,9 +29300,9 @@ } }, "es-abstract": { - "version": "1.18.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.4.tgz", - "integrity": "sha512-xjDAPJRxKc1uoTkdW8MEk7Fq/2bzz3YoCADYniDV7+KITCUdu9c90fj1aKI7nEZFZxRrHlDo3wtma/C6QkhlXQ==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -30462,6 +29341,12 @@ "is-symbol": "^1.0.2" } }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -30548,9 +29433,9 @@ } }, "eslint": { - "version": "7.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", - "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", @@ -30622,9 +29507,9 @@ } }, "globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -30669,48 +29554,30 @@ "object.entries": "^1.1.2" } }, - "eslint-config-airbnb-typescript": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz", - "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^4.4.1", - "eslint-config-airbnb": "^18.2.0", - "eslint-config-airbnb-base": "^14.2.0" - } - }, "eslint-config-prettier": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -30770,9 +29637,9 @@ } }, "eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "requires": { "debug": "^3.2.7", @@ -30791,16 +29658,16 @@ } }, "eslint-plugin-compat": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.11.1.tgz", - "integrity": "sha512-iJyltnaVN9g/MYL3WGb6GFyJs+4mMkumq2E5srxsQIfPqQh14HEE0dtQC/HKDWze+hkwQtSo5DvC3IW5Gmxdtw==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.13.0.tgz", + "integrity": "sha512-cv8IYMuTXm7PIjMVDN2y4k/KVnKZmoNGHNq27/9dLstOLydKblieIv+oe2BN2WthuXnFNhaNvv3N1Bvl4dbIGA==", "dev": true, "requires": { - "@mdn/browser-compat-data": "^3.3.11", - "ast-metadata-inferer": "^0.5.1", - "browserslist": "^4.16.6", - "caniuse-lite": "^1.0.30001245", - "core-js": "^3.15.2", + "@mdn/browser-compat-data": "^3.3.14", + "ast-metadata-inferer": "^0.7.0", + "browserslist": "^4.16.8", + "caniuse-lite": "^1.0.30001251", + "core-js": "^3.16.2", "find-up": "^5.0.0", "lodash.memoize": "4.1.2", "semver": "7.3.5" @@ -30891,26 +29758,26 @@ } }, "eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "version": "2.24.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz", + "integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==", "dev": true, "requires": { "array-includes": "^3.1.3", "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.6.2", "find-up": "^2.0.0", "has": "^1.0.3", - "is-core-module": "^2.4.0", + "is-core-module": "^2.6.0", "minimatch": "^3.0.4", - "object.values": "^1.1.3", + "object.values": "^1.1.4", "pkg-up": "^2.0.0", "read-pkg-up": "^3.0.0", "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" + "tsconfig-paths": "^3.10.1" }, "dependencies": { "debug": { @@ -31061,8 +29928,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -31550,9 +30416,9 @@ "dev": true }, "fastq": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", - "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -31849,9 +30715,9 @@ } }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", + "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", "dev": true }, "for-in": { @@ -32208,9 +31074,9 @@ } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, "growly": { @@ -32266,6 +31132,14 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -32342,6 +31216,13 @@ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "homedir-polyfill": { @@ -32578,8 +31459,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ieee754": { "version": "1.2.1", @@ -32662,6 +31542,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -32735,11 +31621,12 @@ } }, "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-arrayish": { @@ -32749,18 +31636,22 @@ "dev": true }, "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true - }, - "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-buffer": { @@ -32770,9 +31661,9 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-ci": { @@ -32799,9 +31690,9 @@ } }, "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -32817,9 +31708,12 @@ } }, "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-descriptor": { "version": "1.0.2", @@ -32896,10 +31790,13 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-obj": { "version": "1.0.1", @@ -32947,12 +31844,12 @@ "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "is-regexp": { @@ -32974,10 +31871,13 @@ "dev": true }, "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { "version": "1.0.4", @@ -33442,12 +32342,6 @@ "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true } } }, @@ -33568,8 +32462,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} + "dev": true }, "jest-puppeteer": { "version": "5.0.4", @@ -33837,9 +32730,9 @@ } }, "joi": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.1.tgz", - "integrity": "sha512-gDPOwQ5sr+BUxXuPDGrC1pSNcVR/yGGcTI0aCnjYxZEa3za60K/iCQ+OFIkEHWZGVCUcUlXlFKvMmrlmxrG6UQ==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", "dev": true, "requires": { "@hapi/hoek": "^9.0.0", @@ -33877,9 +32770,9 @@ "dev": true }, "jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "requires": { "abab": "^2.0.5", @@ -33907,7 +32800,7 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.5", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, "dependencies": { @@ -34762,9 +33655,9 @@ "dev": true }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, "nanomatch": { @@ -34903,9 +33796,9 @@ } }, "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", "dev": true }, "normalize-package-data": { @@ -35360,9 +34253,9 @@ } }, "parse-headers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", - "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", + "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", "dev": true }, "parse-json": { @@ -36539,15 +35432,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -36560,12 +35444,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, "postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -36975,15 +35853,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -36996,12 +35865,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, "postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -37045,8 +35908,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -38520,9 +37382,9 @@ "dev": true }, "prebuild-install": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.3.tgz", - "integrity": "sha512-iqqSR84tNYQUQHRXalSKdIaM8Ov1QxOVuBNWI7+BzZWv6Ih9k75wOnH1rGQ9WWTaaLkTpxWKIciOF0KyfM74+Q==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "dev": true, "requires": { "detect-libc": "^1.0.3", @@ -38572,14 +37434,6 @@ "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^17.0.1" - }, - "dependencies": { - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - } } }, "process": { @@ -38624,6 +37478,13 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "proxy-addr": { @@ -38781,8 +37642,7 @@ "react-async": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/react-async/-/react-async-10.0.1.tgz", - "integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==", - "requires": {} + "integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==" }, "react-dom": { "version": "17.0.2", @@ -38822,13 +37682,13 @@ "react-icons": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", - "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", - "requires": {} + "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==" }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "react-lifecycles-compat": { "version": "3.0.4", @@ -38836,11 +37696,16 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "react-popper": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", - "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", + "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", "requires": { - "react-fast-compare": "^3.0.1", + "@babel/runtime": "^7.1.2", + "@hypnosphi/create-react-context": "^0.3.1", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", "warning": "^4.0.2" } }, @@ -38855,13 +37720,19 @@ "loose-envify": "^1.4.0", "prop-types": "^15.7.2", "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "react-side-effect": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", - "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==", - "requires": {} + "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" }, "react-transition-group": { "version": "2.9.0", @@ -38994,9 +37865,9 @@ } }, "redux": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", - "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.1.tgz", + "integrity": "sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw==", "requires": { "@babel/runtime": "^7.9.2" } @@ -39268,12 +38139,6 @@ "integrity": "sha1-WtAUcJnROp84qnuZrx1ueGZu038=", "dev": true }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, "file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", @@ -40302,9 +39167,9 @@ } }, "spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "split-string": { @@ -40657,15 +39522,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -40678,12 +39534,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, "postcss": { "version": "7.0.36", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", @@ -41294,9 +40144,9 @@ } }, "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "tsutils": { "version": "3.21.0", @@ -41375,12 +40225,6 @@ "is-typedarray": "^1.0.0" } }, - "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true - }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -41816,9 +40660,9 @@ "dev": true }, "webpack": { - "version": "5.47.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.47.1.tgz", - "integrity": "sha512-cW+Mzy9SCDapFV4OrkHuP6EFV2mAsiQd+gOa3PKtHNoKg6qPqQXZzBlHH+CnQG1osplBCqwsJZ8CfGO6XWah0g==", + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.1.tgz", + "integrity": "sha512-xsn3lwqEKoFvqn4JQggPSRxE4dhsRcysWTqYABAZlmavcoTmwlOb9b1N36Inbt/eIispSkuHa80/FJkDTPos1A==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -41827,6 +40671,7 @@ "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.8.0", @@ -41843,7 +40688,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.2.0", - "webpack-sources": "^3.1.1" + "webpack-sources": "^3.2.0" }, "dependencies": { "acorn": { @@ -41864,23 +40709,23 @@ } }, "webpack-sources": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.1.2.tgz", - "integrity": "sha512-//DeuK5SzM6yFRXNOGK+4tX7QB8PghkL8kFBPyqSlN62oJOUkmby8ptV7+IBGH6BkIuIw5Rjd7OvvwZaoiF4ag==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", "dev": true } } }, "webpack-cli": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.2.tgz", - "integrity": "sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.8.0.tgz", + "integrity": "sha512-+iBSWsX16uVna5aAYN6/wjhJy1q/GKk4KjKvfg90/6hykCTSgozbfz5iRgDTSJt/LgSbYxdBX3KBHeobIs+ZEw==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.0.4", "@webpack-cli/info": "^1.3.0", - "@webpack-cli/serve": "^1.5.1", + "@webpack-cli/serve": "^1.5.2", "colorette": "^1.2.1", "commander": "^7.0.0", "execa": "^5.0.0", @@ -42136,8 +40981,7 @@ "version": "7.5.3", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "dev": true, - "requires": {} + "dev": true }, "xhr": { "version": "2.6.0", diff --git a/client/package.json b/client/package.json index 4b08ebf4..527f7b6a 100644 --- a/client/package.json +++ b/client/package.json @@ -8,14 +8,13 @@ "build": "npm run clean && webpack --config", "clean": "rimraf build", "dev": "npm run build -- configuration/webpack/webpack.config.dev.js", - "e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.ts", - "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.ts", + "e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.js", + "e2e-annotations": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2eAnnotations.test.js", + "e2e-prod": "CXG_URL_BASE='https://cellxgene.cziscience.com/d/pbmc3k.cxg/' jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.js", "fmt": "eslint --fix src __tests__", - "lint": "eslint src __tests__ & npm run type-check", + "lint": "eslint --fix src __tests__", "prod": "npm run build -- configuration/webpack/webpack.config.prod.js", - "test": "jest --testPathIgnorePatterns e2e", - "type-check": "tsc --noEmit" + "test": "jest --testPathIgnorePatterns e2e" }, "engineStrict": true, "engines": { @@ -89,38 +88,10 @@ "@babel/plugin-transform-runtime": "^7.13.15", "@babel/preset-env": "^7.13.15", "@babel/preset-react": "^7.13.13", - "@babel/preset-typescript": "^7.14.5", "@babel/register": "^7.13.16", "@babel/runtime": "^7.13.16", "@blueprintjs/eslint-plugin": "^0.3.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-jest": "^26.1.0", "babel-loader": "^8.1.0", @@ -132,7 +103,7 @@ "codecov": "^3.7.1", "css-loader": "^5.2.4", "eslint": "^7.24.0", - "eslint-config-airbnb-typescript": "^12.3.1", + "eslint-config-airbnb": "^18.2.0", "eslint-config-prettier": "^8.2.0", "eslint-loader": "^4.0.2", "eslint-plugin-compat": "^3.8.0", @@ -172,7 +143,6 @@ "script-ext-html-webpack-plugin": "^2.1.4", "serve-favicon": "^2.5.0", "terser-webpack-plugin": "^5.1.1", - "typescript": "^4.3.5", "webpack": "^5.34.0", "webpack-cli": "^4.6.0", "webpack-dev-middleware": "^4.1.0", @@ -180,10 +150,10 @@ }, "jest": { "testMatch": [ - "**/__tests__/**/?(*.)(spec|test).ts?(x)" + "**/__tests__/**/?(*.)(spec|test).js?(x)" ], "setupFiles": [ - "./__tests__/setupMissingGlobals.ts" + "./__tests__/setupMissingGlobals.js" ], "coverageDirectory": "./coverage/", "collectCoverage": true @@ -193,8 +163,7 @@ "test": { "presets": [ "@babel/preset-env", - "@babel/preset-react", - "@babel/preset-typescript" + "@babel/preset-react" ], "plugins": [ "@babel/plugin-proposal-function-bind", @@ -216,6 +185,12 @@ "loose": true } ], + [ + "@babel/plugin-proposal-private-property-in-object", + { + "loose": true + } + ], "@babel/plugin-proposal-export-namespace-from", "@babel/plugin-transform-react-constant-elements", "@babel/plugin-transform-runtime", diff --git a/client/src/actions/annotation.js b/client/src/actions/annotation.js new file mode 100644 index 00000000..ad2f0db5 --- /dev/null +++ b/client/src/actions/annotation.js @@ -0,0 +1,455 @@ +/* +Action creators for user annotation +*/ +import difference from "lodash.difference"; +import pako from "pako"; +import * as globals from "../globals"; +import { MatrixFBS, AnnotationsHelpers } from "../util/stateManager"; + +const { isUserAnnotation } = AnnotationsHelpers; + +export const annotationCreateCategoryAction = + (newCategoryName, categoryToDuplicate) => async (dispatch, getState) => { + /* + Add a new user-created category to the obs annotations. + + Arguments: + newCategoryName - string name for the category. + categoryToDuplicate - obs category to use for initial values, or null. + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + const { schema } = prevAnnoMatrix; + + /* name must be a string, non-zero length */ + if (typeof newCategoryName !== "string" || newCategoryName.length === 0) + throw new Error("user annotations require string name"); + + /* ensure the name isn't already in use! */ + if (schema.annotations.obsByName[newCategoryName]) + throw new Error("name collision on annotation category create"); + + let initialValue; + let newSchema; + let ctor; + if (categoryToDuplicate) { + /* if we are duplicating a category, retrieve it */ + const catDupSchema = schema.annotations.obsByName[categoryToDuplicate]; + const catDupType = catDupSchema?.type; + if (catDupType !== "string" && catDupType !== "categorical") + throw new Error( + "categoryToDuplicate does not exist or has invalid type" + ); + + const catToDupDf = await prevAnnoMatrix + .base() + .fetch("obs", categoryToDuplicate); + const col = catToDupDf.col(categoryToDuplicate); + initialValue = col.asArray(); + const { categories } = col.summarizeCategorical(); + // all user-created annotations must have the unassigned category + if (!categories.includes(globals.unassignedCategoryLabel)) { + categories.push(globals.unassignedCategoryLabel); + } + ctor = initialValue.constructor; + newSchema = { + ...catDupSchema, + name: newCategoryName, + categories, + writable: true, + }; + } else { + /* else assign to the standard default value */ + initialValue = globals.unassignedCategoryLabel; + ctor = Array; + newSchema = { + name: newCategoryName, + type: "categorical", + categories: [globals.unassignedCategoryLabel], + writable: true, + }; + } + + const obsCrossfilter = prevObsCrossfilter.addObsColumn( + newSchema, + ctor, + initialValue + ); + + dispatch({ + type: "annotation: create category", + data: newCategoryName, + categoryToDuplicate, + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + }); + }; + +export const annotationRenameCategoryAction = + (oldCategoryName, newCategoryName) => (dispatch, getState) => { + /* + Rename a user-created annotation category + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, oldCategoryName)) + throw new Error("not a user annotation"); + + /* name must be a string, non-zero length */ + if (typeof newCategoryName !== "string" || newCategoryName.length === 0) + throw new Error("user annotations require string name"); + + if (oldCategoryName === newCategoryName) return; + + const obsCrossfilter = prevObsCrossfilter.renameObsColumn( + oldCategoryName, + newCategoryName + ); + + dispatch({ + type: "annotation: category edited", + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + metadataField: oldCategoryName, + newCategoryText: newCategoryName, + data: newCategoryName, + }); + }; + +export const annotationDeleteCategoryAction = + (categoryName) => (dispatch, getState) => { + /* + Delete a user-created category + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, categoryName)) + throw new Error("not a user annotation"); + + const obsCrossfilter = prevObsCrossfilter.dropObsColumn(categoryName); + dispatch({ + type: "annotation: delete category", + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + metadataField: categoryName, + }); + }; + +export const annotationCreateLabelInCategory = + (categoryName, labelName, assignSelected) => async (dispatch, getState) => { + /* + Add a new label to a user-defined category. If assignSelected is true, assign + the label to all currently selected cells. + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, categoryName)) + throw new Error("not a user annotation"); + + let obsCrossfilter = prevObsCrossfilter.addObsAnnoCategory( + categoryName, + labelName + ); + if (assignSelected) { + obsCrossfilter = await obsCrossfilter.setObsColumnValues( + categoryName, + prevObsCrossfilter.allSelectedLabels(), + labelName + ); + } + + dispatch({ + type: "annotation: add new label to category", + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + metadataField: categoryName, + newLabelText: labelName, + assignSelectedCells: assignSelected, + }); + }; + +export const annotationDeleteLabelFromCategory = + (categoryName, labelName) => async (dispatch, getState) => { + /* + delete a label from a user-defined category + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, categoryName)) + throw new Error("not a user annotation"); + + const obsCrossfilter = await prevObsCrossfilter.removeObsAnnoCategory( + categoryName, + labelName, + globals.unassignedCategoryLabel + ); + + dispatch({ + type: "annotation: delete label", + metadataField: categoryName, + label: labelName, + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + }); + }; + +export const annotationRenameLabelInCategory = + (categoryName, oldLabelName, newLabelName) => async (dispatch, getState) => { + /* + label name change + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, categoryName)) + throw new Error("not a user annotation"); + + let obsCrossfilter = await prevObsCrossfilter.resetObsColumnValues( + categoryName, + oldLabelName, + newLabelName + ); + obsCrossfilter = await obsCrossfilter.removeObsAnnoCategory( + categoryName, + oldLabelName, + globals.unassignedCategoryLabel + ); + + dispatch({ + type: "annotation: label edited", + editedLabel: newLabelName, + metadataField: categoryName, + label: oldLabelName, + annoMatrix: obsCrossfilter.annoMatrix, + obsCrossfilter, + }); + }; + +export const annotationLabelCurrentSelection = + (categoryName, labelName) => async (dispatch, getState) => { + /* + set the label on all currently selected + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); + if (!prevAnnoMatrix || !prevObsCrossfilter) return; + if (!isUserAnnotation(prevAnnoMatrix, categoryName)) + throw new Error("not a user annotation"); + + const obsCrossfilter = await prevObsCrossfilter.setObsColumnValues( + categoryName, + prevObsCrossfilter.allSelectedLabels(), + labelName + ); + + dispatch({ + type: "annotation: label current cell selection", + metadataField: categoryName, + label: labelName, + obsCrossfilter, + annoMatrix: obsCrossfilter.annoMatrix, + }); + }; + +function writableAnnotations(annoMatrix) { + return annoMatrix.schema.annotations.obs.columns + .filter((s) => s.writable) + .map((s) => s.name); +} + +export const needToSaveObsAnnotations = (annoMatrix, lastSavedAnnoMatrix) => { + /* + Return true if there are LIKELY user-defined annotation modifications between the two + annoMatrices. Technically not an action creator, but intimately intertwined + with the save process. + + Two conditions will trigger a need to save: + * the collection of user-defined columns have changed + * the contents of the user-defined columns have change + */ + + annoMatrix = annoMatrix.base(); + + // if the annoMatrix hasn't changed, we are guaranteed no changes to the matrix schema or contents. + if (annoMatrix === lastSavedAnnoMatrix) return false; + + // if the schema has changed, we need to save + const currentWritable = writableAnnotations(annoMatrix); + if (difference(currentWritable, writableAnnotations(lastSavedAnnoMatrix))) { + return true; + } + + // no schema changes; check for change in contents + return currentWritable.some( + (col) => annoMatrix.col(col) !== lastSavedAnnoMatrix.col(col) + ); +}; + +export const saveObsAnnotationsAction = () => async (dispatch, getState) => { + /* + Save the user-created obs annotations IF any have changed. + */ + const state = getState(); + const { annotations, autosave } = state; + const { dataCollectionNameIsReadOnly, dataCollectionName } = annotations; + const { lastSavedAnnoMatrix, saveInProgress } = autosave; + + const annoMatrix = state.annoMatrix.base(); + + if (saveInProgress || annoMatrix === lastSavedAnnoMatrix) return; + if (!needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix)) { + dispatch({ + type: "writable obs annotations - save complete", + lastSavedAnnoMatrix: annoMatrix, + }); + return; + } + + /* + Else, we really do need to save + */ + + dispatch({ + type: "writable obs annotations - save started", + }); + + const df = await annoMatrix.fetch("obs", writableAnnotations(annoMatrix)); + const matrix = MatrixFBS.encodeMatrixFBS(df); + const compressedMatrix = pako.deflate(matrix); + try { + const queryString = + !dataCollectionNameIsReadOnly && !!dataCollectionName + ? `?annotation-collection-name=${encodeURIComponent( + dataCollectionName + )}` + : ""; + const res = await fetch( + `${globals.API.prefix}${globals.API.version}annotations/obs${queryString}`, + { + method: "PUT", + body: compressedMatrix, + headers: new Headers({ + "Content-Type": "application/octet-stream", + }), + credentials: "include", + } + ); + if (res.ok) { + dispatch({ + type: "writable obs annotations - save complete", + lastSavedAnnoMatrix: annoMatrix, + }); + } else { + dispatch({ + type: "writable obs annotations - save error", + message: `HTTP error ${res.status} - ${res.statusText}`, + res, + }); + } + } catch (error) { + dispatch({ + type: "writable obs annotations - save error", + message: error.toString(), + error, + }); + } +}; + +export const saveGenesetsAction = () => async (dispatch, getState) => { + const state = getState(); + + // bail if gene sets not available, or in readonly mode. + const { config } = state; + const { lastTid, genesets } = state.genesets; + + const genesetsAreAvailable = + config?.parameters?.annotations_genesets ?? false; + const genesetsReadonly = + config?.parameters?.annotations_genesets_readonly ?? true; + if (!genesetsAreAvailable || genesetsReadonly) { + // our non-save was completed! + return dispatch({ + type: "autosave: genesets complete", + lastSavedGenesets: genesets, + }); + } + + dispatch({ + type: "autosave: genesets started", + }); + + /* Create the JSON OTA data structure */ + const tid = (lastTid ?? 0) + 1; + const genesetsOTA = []; + for (const [name, gs] of genesets) { + const genes = []; + for (const g of gs.genes.values()) { + genes.push({ + gene_symbol: g.geneSymbol, + gene_description: g.geneDescription, + }); + } + genesetsOTA.push({ + geneset_name: name, + geneset_description: gs.genesetDescription, + genes, + }); + } + const ota = { + tid, + genesets: genesetsOTA, + }; + + /* Save to server */ + try { + const { dataCollectionNameIsReadOnly, dataCollectionName } = + state.annotations; + const queryString = + !dataCollectionNameIsReadOnly && !!dataCollectionName + ? `?annotation-collection-name=${encodeURIComponent( + dataCollectionName + )}` + : ""; + + const res = await fetch( + `${globals.API.prefix}${globals.API.version}genesets${queryString}`, + { + method: "PUT", + headers: new Headers({ + Accept: "application/json", + "Content-Type": "application/json", + }), + body: JSON.stringify(ota), + credentials: "include", + } + ); + if (!res.ok) { + return dispatch({ + type: "autosave: genesets error", + message: `HTTP error ${res.status} - ${res.statusText}`, + res, + }); + } + return Promise.all([ + dispatch({ + type: "autosave: genesets complete", + lastSavedGenesets: genesets, + }), + dispatch({ + type: "geneset: set tid", + tid, + }), + ]); + } catch (error) { + return dispatch({ + type: "autosave: genesets error", + message: error.toString(), + error, + }); + } +}; diff --git a/client/src/actions/annotation.ts b/client/src/actions/annotation.ts deleted file mode 100644 index df1406d1..00000000 --- a/client/src/actions/annotation.ts +++ /dev/null @@ -1,530 +0,0 @@ -/* -Action creators for user annotation -*/ -import difference from "lodash.difference"; -import pako from "pako"; -import * as globals from "../globals"; -import { MatrixFBS, AnnotationsHelpers } from "../util/stateManager"; - -const { isUserAnnotation } = AnnotationsHelpers; - -export const annotationCreateCategoryAction = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - newCategoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryToDuplicate: any - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - /* - Add a new user-created category to the obs annotations. - - Arguments: - newCategoryName - string name for the category. - categoryToDuplicate - obs category to use for initial values, or null. - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - const { schema } = prevAnnoMatrix; - - /* name must be a string, non-zero length */ - if (typeof newCategoryName !== "string" || newCategoryName.length === 0) - throw new Error("user annotations require string name"); - - /* ensure the name isn't already in use! */ - if (schema.annotations.obsByName[newCategoryName]) - throw new Error("name collision on annotation category create"); - - let initialValue; - let newSchema; - let ctor; - if (categoryToDuplicate) { - /* if we are duplicating a category, retrieve it */ - const catDupSchema = schema.annotations.obsByName[categoryToDuplicate]; - const catDupType = catDupSchema?.type; - if (catDupType !== "string" && catDupType !== "categorical") - throw new Error("categoryToDuplicate does not exist or has invalid type"); - - const catToDupDf = await prevAnnoMatrix - .base() - .fetch("obs", categoryToDuplicate); - const col = catToDupDf.col(categoryToDuplicate); - initialValue = col.asArray(); - const { categories } = col.summarizeCategorical(); - // all user-created annotations must have the unassigned category - if (!categories.includes(globals.unassignedCategoryLabel)) { - categories.push(globals.unassignedCategoryLabel); - } - ctor = initialValue.constructor; - newSchema = { - ...catDupSchema, - name: newCategoryName, - categories, - writable: true, - }; - } else { - /* else assign to the standard default value */ - initialValue = globals.unassignedCategoryLabel; - ctor = Array; - newSchema = { - name: newCategoryName, - type: "categorical", - categories: [globals.unassignedCategoryLabel], - writable: true, - }; - } - - const obsCrossfilter = prevObsCrossfilter.addObsColumn( - newSchema, - ctor, - initialValue - ); - - dispatch({ - type: "annotation: create category", - data: newCategoryName, - categoryToDuplicate, - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - }); -}; - -export const annotationRenameCategoryAction = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - oldCategoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - newCategoryName: any - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => (dispatch: any, getState: any) => { - /* - Rename a user-created annotation category - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, oldCategoryName)) - throw new Error("not a user annotation"); - - /* name must be a string, non-zero length */ - if (typeof newCategoryName !== "string" || newCategoryName.length === 0) - throw new Error("user annotations require string name"); - - if (oldCategoryName === newCategoryName) return; - - const obsCrossfilter = prevObsCrossfilter.renameObsColumn( - oldCategoryName, - newCategoryName - ); - - dispatch({ - type: "annotation: category edited", - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - metadataField: oldCategoryName, - newCategoryText: newCategoryName, - data: newCategoryName, - }); -}; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const annotationDeleteCategoryAction = (categoryName: any) => ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - /* - Delete a user-created category - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, categoryName)) - throw new Error("not a user annotation"); - - const obsCrossfilter = prevObsCrossfilter.dropObsColumn(categoryName); - dispatch({ - type: "annotation: delete category", - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - metadataField: categoryName, - }); -}; - -export const annotationCreateLabelInCategory = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labelName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - assignSelected: any // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - /* - Add a new label to a user-defined category. If assignSelected is true, assign - the label to all currently selected cells. - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, categoryName)) - throw new Error("not a user annotation"); - - let obsCrossfilter = prevObsCrossfilter.addObsAnnoCategory( - categoryName, - labelName - ); - if (assignSelected) { - obsCrossfilter = await obsCrossfilter.setObsColumnValues( - categoryName, - prevObsCrossfilter.allSelectedLabels(), - labelName - ); - } - - dispatch({ - type: "annotation: add new label to category", - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - metadataField: categoryName, - newLabelText: labelName, - assignSelectedCells: assignSelected, - }); -}; - -export const annotationDeleteLabelFromCategory = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labelName: any // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - /* - delete a label from a user-defined category - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, categoryName)) - throw new Error("not a user annotation"); - - const obsCrossfilter = await prevObsCrossfilter.removeObsAnnoCategory( - categoryName, - labelName, - globals.unassignedCategoryLabel - ); - - dispatch({ - type: "annotation: delete label", - metadataField: categoryName, - label: labelName, - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - }); -}; - -export const annotationRenameLabelInCategory = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - oldLabelName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - newLabelName: any - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - /* - label name change - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, categoryName)) - throw new Error("not a user annotation"); - - let obsCrossfilter = await prevObsCrossfilter.resetObsColumnValues( - categoryName, - oldLabelName, - newLabelName - ); - obsCrossfilter = await obsCrossfilter.removeObsAnnoCategory( - categoryName, - oldLabelName, - globals.unassignedCategoryLabel - ); - - dispatch({ - type: "annotation: label edited", - editedLabel: newLabelName, - metadataField: categoryName, - label: oldLabelName, - annoMatrix: obsCrossfilter.annoMatrix, - obsCrossfilter, - }); -}; - -export const annotationLabelCurrentSelection = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryName: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labelName: any - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - /* - set the label on all currently selected - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); - if (!prevAnnoMatrix || !prevObsCrossfilter) return; - if (!isUserAnnotation(prevAnnoMatrix, categoryName)) - throw new Error("not a user annotation"); - - const obsCrossfilter = await prevObsCrossfilter.setObsColumnValues( - categoryName, - prevObsCrossfilter.allSelectedLabels(), - labelName - ); - - dispatch({ - type: "annotation: label current cell selection", - metadataField: categoryName, - label: labelName, - obsCrossfilter, - annoMatrix: obsCrossfilter.annoMatrix, - }); -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function writableAnnotations(annoMatrix: any) { - return ( - annoMatrix.schema.annotations.obs.columns - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((s: any) => s.writable) - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .map((s: any) => s.name) - ); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const needToSaveObsAnnotations = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - annoMatrix: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - lastSavedAnnoMatrix: any -) => { - /* - Return true if there are LIKELY user-defined annotation modifications between the two - annoMatrices. Technically not an action creator, but intimately intertwined - with the save process. - - Two conditions will trigger a need to save: - * the collection of user-defined columns have changed - * the contents of the user-defined columns have change - */ - - annoMatrix = annoMatrix.base(); - - // if the annoMatrix hasn't changed, we are guaranteed no changes to the matrix schema or contents. - if (annoMatrix === lastSavedAnnoMatrix) return false; - - // if the schema has changed, we need to save - const currentWritable = writableAnnotations(annoMatrix); - if (difference(currentWritable, writableAnnotations(lastSavedAnnoMatrix))) { - return true; - } - - // no schema changes; check for change in contents - return currentWritable.some( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (col: any) => annoMatrix.col(col) !== lastSavedAnnoMatrix.col(col) - ); -}; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const saveObsAnnotationsAction = () => async ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - /* - Save the user-created obs annotations IF any have changed. - */ - const state = getState(); - const { annotations, autosave } = state; - const { dataCollectionNameIsReadOnly, dataCollectionName } = annotations; - const { lastSavedAnnoMatrix, saveInProgress } = autosave; - - const annoMatrix = state.annoMatrix.base(); - - if (saveInProgress || annoMatrix === lastSavedAnnoMatrix) return; - if (!needToSaveObsAnnotations(annoMatrix, lastSavedAnnoMatrix)) { - dispatch({ - type: "writable obs annotations - save complete", - lastSavedAnnoMatrix: annoMatrix, - }); - return; - } - - /* - Else, we really do need to save - */ - - dispatch({ - type: "writable obs annotations - save started", - }); - - const df = await annoMatrix.fetch("obs", writableAnnotations(annoMatrix)); - const matrix = MatrixFBS.encodeMatrixFBS(df); - const compressedMatrix = pako.deflate(matrix); - try { - const queryString = - !dataCollectionNameIsReadOnly && !!dataCollectionName - ? `?annotation-collection-name=${encodeURIComponent( - dataCollectionName - )}` - : ""; - const res = await fetch( - `${globals.API.prefix}${globals.API.version}annotations/obs${queryString}`, - { - method: "PUT", - body: compressedMatrix, - headers: new Headers({ - "Content-Type": "application/octet-stream", - }), - credentials: "include", - } - ); - if (res.ok) { - dispatch({ - type: "writable obs annotations - save complete", - lastSavedAnnoMatrix: annoMatrix, - }); - } else { - dispatch({ - type: "writable obs annotations - save error", - message: `HTTP error ${res.status} - ${res.statusText}`, - res, - }); - } - } catch (error) { - dispatch({ - type: "writable obs annotations - save error", - message: error.toString(), - error, - }); - } -}; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const saveGenesetsAction = () => async ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - const state = getState(); - - // bail if gene sets not available, or in readonly mode. - const { config } = state; - const { lastTid, genesets } = state.genesets; - - const genesetsAreAvailable = - config?.parameters?.annotations_genesets ?? false; - const genesetsReadonly = - config?.parameters?.annotations_genesets_readonly ?? true; - if (!genesetsAreAvailable || genesetsReadonly) { - // our non-save was completed! - return dispatch({ - type: "autosave: genesets complete", - lastSavedGenesets: genesets, - }); - } - - dispatch({ - type: "autosave: genesets started", - }); - - /* Create the JSON OTA data structure */ - const tid = (lastTid ?? 0) + 1; - const genesetsOTA = []; - for (const [name, gs] of genesets) { - const genes = []; - for (const g of gs.genes.values()) { - genes.push({ - gene_symbol: g.geneSymbol, - gene_description: g.geneDescription, - }); - } - genesetsOTA.push({ - geneset_name: name, - geneset_description: gs.genesetDescription, - genes, - }); - } - const ota = { - tid, - genesets: genesetsOTA, - }; - - /* Save to server */ - try { - const { - dataCollectionNameIsReadOnly, - dataCollectionName, - } = state.annotations; - const queryString = - !dataCollectionNameIsReadOnly && !!dataCollectionName - ? `?annotation-collection-name=${encodeURIComponent( - dataCollectionName - )}` - : ""; - - const res = await fetch( - `${globals.API.prefix}${globals.API.version}genesets${queryString}`, - { - method: "PUT", - headers: new Headers({ - Accept: "application/json", - "Content-Type": "application/json", - }), - body: JSON.stringify(ota), - credentials: "include", - } - ); - if (!res.ok) { - return dispatch({ - type: "autosave: genesets error", - message: `HTTP error ${res.status} - ${res.statusText}`, - res, - }); - } - return await Promise.all([ - dispatch({ - type: "autosave: genesets complete", - lastSavedGenesets: genesets, - }), - dispatch({ - type: "geneset: set tid", - tid, - }), - ]); - } catch (error) { - return dispatch({ - type: "autosave: genesets error", - message: error.toString(), - error, - }); - } -}; diff --git a/client/src/actions/embedding.js b/client/src/actions/embedding.js new file mode 100644 index 00000000..5b511189 --- /dev/null +++ b/client/src/actions/embedding.js @@ -0,0 +1,47 @@ +/* +action creators related to embeddings choice +*/ + +import { AnnoMatrixObsCrossfilter } from "../annoMatrix"; +import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers"; + +export async function _switchEmbedding( + prevAnnoMatrix, + prevCrossfilter, + newEmbeddingName +) { + /* + DRY helper used by embedding action creators + */ + const base = prevAnnoMatrix.base(); + const embeddingDf = await base.fetch("emb", newEmbeddingName); + const annoMatrix = _setEmbeddingSubset(prevAnnoMatrix, embeddingDf); + const obsCrossfilter = await new AnnoMatrixObsCrossfilter( + annoMatrix, + prevCrossfilter.obsCrossfilter + ).select("emb", newEmbeddingName, { + mode: "all", + }); + return [annoMatrix, obsCrossfilter]; +} + +export const layoutChoiceAction = + (newLayoutChoice) => async (dispatch, getState) => { + /* + On layout choice, make sure we have selected all on the previous layout, AND the new + layout. + */ + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevCrossfilter } = + getState(); + const [annoMatrix, obsCrossfilter] = await _switchEmbedding( + prevAnnoMatrix, + prevCrossfilter, + newLayoutChoice + ); + dispatch({ + type: "set layout choice", + layoutChoice: newLayoutChoice, + obsCrossfilter, + annoMatrix, + }); + }; diff --git a/client/src/actions/embedding.ts b/client/src/actions/embedding.ts deleted file mode 100644 index 3cfcb555..00000000 --- a/client/src/actions/embedding.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* -action creators related to embeddings choice -*/ - -import { Action, ActionCreator } from "redux"; -import { ThunkAction } from "redux-thunk"; -import { AnnoMatrixObsCrossfilter } from "../annoMatrix"; -import type { AppDispatch, RootState } from "../reducers"; -import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers"; -import { Field } from "../common/types/schema"; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export async function _switchEmbedding( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - prevAnnoMatrix: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - prevCrossfilter: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - newEmbeddingName: any -) { - /* - DRY helper used by embedding action creators - */ - const base = prevAnnoMatrix.base(); - const embeddingDf = await base.fetch("emb", newEmbeddingName); - const annoMatrix = _setEmbeddingSubset(prevAnnoMatrix, embeddingDf); - const obsCrossfilter = await new AnnoMatrixObsCrossfilter( - annoMatrix, - prevCrossfilter.obsCrossfilter - ).select(Field.emb, newEmbeddingName, { - mode: "all", - }); - return [annoMatrix, obsCrossfilter]; -} - -export const layoutChoiceAction: ActionCreator< - ThunkAction, RootState, never, Action<"set layout choice">> -> = - (newLayoutChoice: string) => - async (dispatch: AppDispatch, getState: () => RootState): Promise => { - /* - On layout choice, make sure we have selected all on the previous layout, AND the new - layout. - */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevCrossfilter, - } = getState(); - const [annoMatrix, obsCrossfilter] = await _switchEmbedding( - prevAnnoMatrix, - prevCrossfilter, - newLayoutChoice - ); - dispatch({ - type: "set layout choice", - layoutChoice: newLayoutChoice, - obsCrossfilter, - annoMatrix, - }); -}; diff --git a/client/src/actions/geneset.ts b/client/src/actions/geneset.js similarity index 51% rename from client/src/actions/geneset.ts rename to client/src/actions/geneset.js index 4578aa46..35882757 100644 --- a/client/src/actions/geneset.ts +++ b/client/src/actions/geneset.js @@ -21,45 +21,34 @@ The behavior manifest in these action creators: Note that crossfilter indices are lazy created, as needed. */ -import { Dataframe } from "../util/dataframe"; - -export const genesetDelete = - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - (genesetName: any) => (dispatch: any, getState: any) => { - const state = getState(); - const { genesets } = state; - const gs = genesets?.genesets?.get(genesetName) ?? {}; - const geneSymbols = Array.from(gs.genes.keys()); - const obsCrossfilter = dropGeneset( - dispatch, - state, - genesetName, - geneSymbols - ); - if (genesetName === state.colors.colorAccessor) { - dispatch({ - type: "reset colorscale", - }); - } +export const genesetDelete = (genesetName) => (dispatch, getState) => { + const state = getState(); + const { genesets } = state; + const gs = genesets?.genesets?.get(genesetName) ?? {}; + const geneSymbols = Array.from(gs.genes.keys()); + const obsCrossfilter = dropGeneset(dispatch, state, genesetName, geneSymbols); + if (genesetName === state.colors.colorAccessor) { dispatch({ - type: "geneset: delete", - genesetName, - obsCrossfilter, - annoMatrix: obsCrossfilter.annoMatrix, + type: "reset colorscale", }); - }; + } + dispatch({ + type: "geneset: delete", + genesetName, + obsCrossfilter, + annoMatrix: obsCrossfilter.annoMatrix, + }); +}; export const genesetAddGenes = - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - (genesetName: any, genes: any) => async (dispatch: any, getState: any) => { + (genesetName, genes) => async (dispatch, getState) => { const state = getState(); const { obsCrossfilter: prevObsCrossfilter, annoMatrix } = state; const { schema } = annoMatrix; const varIndex = schema.annotations.var.index; - const df: Dataframe = await annoMatrix.fetch("var", varIndex); + const df = await annoMatrix.fetch("var", varIndex); const geneNames = df.col(varIndex).asArray(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genes = genes.reduce((acc: any, gene: any) => { + genes = genes.reduce((acc, gene) => { if (geneNames.indexOf(gene.geneSymbol) === -1) { postUserErrorToast( `${gene.geneSymbol} doesn't appear to be a valid gene name.` @@ -88,8 +77,7 @@ export const genesetAddGenes = }; export const genesetDeleteGenes = - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - (genesetName: any, geneSymbols: any) => (dispatch: any, getState: any) => { + (genesetName, geneSymbols) => (dispatch, getState) => { const state = getState(); const obsCrossfilter = dropGeneset( dispatch, @@ -110,14 +98,7 @@ export const genesetDeleteGenes = Private */ -function dropGenesetSummaryDimension( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - obsCrossfilter: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - state: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetName: any -) { +function dropGenesetSummaryDimension(obsCrossfilter, state, genesetName) { const { annoMatrix, genesets } = state; const varIndex = annoMatrix.schema.annotations?.var?.index; const gs = genesets?.genesets?.get(genesetName) ?? {}; @@ -133,8 +114,7 @@ function dropGenesetSummaryDimension( return obsCrossfilter.dropDimension("X", query); } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function dropGeneDimension(obsCrossfilter: any, state: any, gene: any) { +function dropGeneDimension(obsCrossfilter, state, gene) { const { annoMatrix } = state; const varIndex = annoMatrix.schema.annotations?.var?.index; const query = { @@ -147,21 +127,10 @@ function dropGeneDimension(obsCrossfilter: any, state: any, gene: any) { return obsCrossfilter.dropDimension("X", query); } -function dropGeneset( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - state: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetName: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - geneSymbols: any -) { +function dropGeneset(dispatch, state, genesetName, geneSymbols) { const { obsCrossfilter: prevObsCrossfilter } = state; const obsCrossfilter = geneSymbols.reduce( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (crossfilter: any, gene: any) => - dropGeneDimension(crossfilter, state, gene), + (crossfilter, gene) => dropGeneDimension(crossfilter, state, gene), dropGenesetSummaryDimension(prevObsCrossfilter, state, genesetName) ); dispatch({ @@ -169,8 +138,7 @@ function dropGeneset( continuousNamespace: { isGeneSetSummary: true }, selection: genesetName, }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - geneSymbols.forEach((g: any) => + geneSymbols.forEach((g) => dispatch({ type: "continuous metadata histogram cancel", continuousNamespace: { isUserDefined: true }, diff --git a/client/src/actions/index.ts b/client/src/actions/index.js similarity index 65% rename from client/src/actions/index.ts rename to client/src/actions/index.js index 49c5d115..c0fb7f48 100644 --- a/client/src/actions/index.ts +++ b/client/src/actions/index.js @@ -1,4 +1,3 @@ -import type { Config } from "../globals"; import * as globals from "../globals"; import { AnnoMatrixLoader, AnnoMatrixObsCrossfilter } from "../annoMatrix"; import { @@ -12,12 +11,8 @@ import * as annoActions from "./annotation"; import * as viewActions from "./viewStack"; import * as embActions from "./embedding"; import * as genesetActions from "./geneset"; -import { AppDispatch, RootState } from "../reducers"; -import { EmbeddingSchema, Schema } from "../common/types/schema"; -import { UserInfoPayload } from "../reducers/userInfo"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function setGlobalConfig(config: any) { +function setGlobalConfig(config) { /** * Set any global run-time config not _exclusively_ managed by the config reducer. * This should only set fields defined in globals.globalConfig. @@ -30,8 +25,7 @@ function setGlobalConfig(config: any) { /* return promise fetching user-configured colors */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -async function userColorsFetchAndLoad(dispatch: any) { +async function userColorsFetchAndLoad(dispatch) { return fetchJson("colors").then((response) => dispatch({ type: "universe: user color load success", @@ -40,38 +34,36 @@ async function userColorsFetchAndLoad(dispatch: any) { ); } -async function schemaFetch(): Promise<{ schema: Schema }> { - return fetchJson<{ schema: Schema }>("schema"); +async function schemaFetch() { + return fetchJson("schema"); } -async function configFetch(dispatch: AppDispatch): Promise { - const response = await fetchJson<{ config: globals.Config }>("config"); - const config = { ...globals.configDefaults, ...response.config }; +async function configFetch(dispatch) { + return fetchJson("config").then((response) => { + const config = { ...globals.configDefaults, ...response.config }; - setGlobalConfig(config); + setGlobalConfig(config); - dispatch({ - type: "configuration load complete", - config, + dispatch({ + type: "configuration load complete", + config, + }); + return config; }); - return config; } -async function userInfoFetch(dispatch: AppDispatch): Promise { - return fetchJson<{ userinfo: UserInfoPayload }>("userinfo").then( - (response) => { - const { userinfo: userInfo } = response || {}; - dispatch({ - type: "userInfo load complete", - userInfo, - }); - return userInfo; - } - ); +async function userInfoFetch(dispatch) { + return fetchJson("userinfo").then((response) => { + const { userinfo: userInfo } = response || {}; + dispatch({ + type: "userInfo load complete", + userInfo, + }); + return userInfo; + }); } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -async function genesetsFetch(dispatch: any, config: any) { +async function genesetsFetch(dispatch, config) { /* request genesets ONLY if the backend supports the feature */ const defaultResponse = { genesets: [], @@ -92,32 +84,26 @@ async function genesetsFetch(dispatch: any, config: any) { } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function prefetchEmbeddings(annoMatrix: any) { +function prefetchEmbeddings(annoMatrix) { /* prefetch requests for all embeddings */ const { schema } = annoMatrix; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const available = schema.layout.obs.map((v: any) => v.name); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - available.forEach((embName: any) => annoMatrix.prefetch("emb", embName)); + const available = schema.layout.obs.map((v) => v.name); + available.forEach((embName) => annoMatrix.prefetch("emb", embName)); } /* Application bootstrap */ -const doInitialDataLoad = (): (( - dispatch: AppDispatch, - getState: () => RootState -) => void) => - catchErrorsWrap(async (dispatch: AppDispatch) => { +const doInitialDataLoad = () => + catchErrorsWrap(async (dispatch) => { dispatch({ type: "initial data load start" }); try { const [config, schema] = await Promise.all([ configFetch(dispatch), - schemaFetch(), + schemaFetch(dispatch), userColorsFetchAndLoad(dispatch), userInfoFetch(dispatch), ]); @@ -140,7 +126,7 @@ const doInitialDataLoad = (): (( const layoutSchema = schema?.schema?.layout?.obs ?? []; if ( defaultEmbedding && - layoutSchema.some((s: EmbeddingSchema) => s.name === defaultEmbedding) + layoutSchema.some((s) => s.name === defaultEmbedding) ) { dispatch(embActions.layoutChoiceAction(defaultEmbedding)); } @@ -149,25 +135,21 @@ const doInitialDataLoad = (): (( } }, true); -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -function requestSingleGeneExpressionCountsForColoringPOST(gene: any) { +function requestSingleGeneExpressionCountsForColoringPOST(gene) { return { type: "color by expression", gene, }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const requestUserDefinedGene = (gene: any) => ({ +const requestUserDefinedGene = (gene) => ({ type: "request user defined gene success", - data: { genes: [gene], }, }); -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const dispatchDiffExpErrors = (dispatch: any, response: any) => { +const dispatchDiffExpErrors = (dispatch, response) => { switch (response.status) { case 403: dispatchNetworkErrorMessageToUser( @@ -191,16 +173,8 @@ const dispatchDiffExpErrors = (dispatch: any, response: any) => { }; const requestDifferentialExpression = - ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - set1: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - set2: any, - num_genes = 50 - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - ) => - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - async (dispatch: any, getState: any) => { + (set1, set2, num_genes = 50) => + async (dispatch, getState) => { dispatch({ type: "request differential expression started" }); try { /* @@ -248,9 +222,7 @@ const requestDifferentialExpression = const varIndex = await annoMatrix.fetch("var", varIndexName); const diffexpLists = { negative: [], positive: [] }; for (const polarity of Object.keys(diffexpLists)) { - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - diffexpLists[polarity] = response[polarity].map((v: any) => [ + diffexpLists[polarity] = response[polarity].map((v) => [ varIndex.at(v[0], varIndexName), ...v.slice(1), ]); @@ -269,10 +241,10 @@ const requestDifferentialExpression = } }; -function fetchJson(pathAndQuery: string): Promise { - return doJsonRequest( +function fetchJson(pathAndQuery) { + return doJsonRequest( `${globals.API.prefix}${globals.API.version}${pathAndQuery}` - ) as Promise; + ); } export default { diff --git a/client/src/actions/selection.js b/client/src/actions/selection.js new file mode 100644 index 00000000..19509dc0 --- /dev/null +++ b/client/src/actions/selection.js @@ -0,0 +1,192 @@ +/* +Action creators for selection +*/ +export const selectContinuousMetadataAction = + (type, query, range, oldProps = {}) => + async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter } = getState(); + + const selection = range + ? { + mode: "range", + lo: range[0], + hi: range[1], + inclusive: true, // [lo, hi] incluisve selection + } + : { mode: "all" }; + + const obsCrossfilter = await prevObsCrossfilter.select(...query, selection); + + dispatch({ + type, + obsCrossfilter, + range, + ...oldProps, + }); + }; + +export const selectCategoricalMetadataAction = + ( + type, // action type + metadataField, // annotation category name + labels, + label, // the label being selected/deselected + isSelected, // bool + oldProps = {} + ) => + async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter, categoricalSelection } = + getState(); + + const labelSelectionState = new Map(categoricalSelection[metadataField]); + labels.forEach( + (l) => labelSelectionState.has(l) || labelSelectionState.set(l, true) + ); + labelSelectionState.set(label, isSelected); + + const values = Array.from(labelSelectionState.keys()).filter((k) => + labelSelectionState.get(k) + ); + const selection = { + mode: "exact", + values, + }; + const obsCrossfilter = await prevObsCrossfilter.select( + "obs", + metadataField, + selection + ); + + dispatch({ + type, + obsCrossfilter, + metadataField, + labelSelectionState, + ...oldProps, + }); + }; + +export const selectCategoricalAllMetadataAction = + ( + type, // action type + metadataField, // annotation category name + labels, + isSelected, // bool, select all or none + oldProps = {} + ) => + async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter, categoricalSelection } = + getState(); + + const labelSelectionState = new Map(categoricalSelection[metadataField]); + labels.forEach((label) => labelSelectionState.set(label, isSelected)); + + const selection = { mode: isSelected ? "all" : "none" }; + const obsCrossfilter = await prevObsCrossfilter.select( + "obs", + metadataField, + selection + ); + + dispatch({ + type, + obsCrossfilter, + metadataField, + labelSelectionState, + ...oldProps, + }); + }; + +/** + ** Graph selection-related actions + **/ + +export const graphBrushStartAction = () => + /* no change to crossfilter until a change fires */ + ({ type: "graph brush start" }); + +const _graphBrushWithinRectAction = + (type, embName, brushCoords) => async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter } = getState(); + + const selection = { mode: "within-rect", ...brushCoords }; + const obsCrossfilter = await prevObsCrossfilter.select( + "emb", + embName, + selection + ); + + dispatch({ + type, + obsCrossfilter, + brushCoords, + }); + }; + +const _graphAllAction = (type, embName) => async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter } = getState(); + + const obsCrossfilter = await prevObsCrossfilter.select("emb", embName, { + mode: "all", + }); + + dispatch({ + type, + obsCrossfilter, + }); +}; + +export const graphBrushChangeAction = (embName, brushCoords) => + _graphBrushWithinRectAction("graph brush change", embName, brushCoords); + +export const graphBrushEndAction = (embName, brushCoords) => + _graphBrushWithinRectAction("graph brush end", embName, brushCoords); + +export const graphBrushCancelAction = (embName) => + _graphAllAction("graph brush cancel", embName); +export const graphBrushDeselectAction = (embName) => + _graphAllAction("graph brush deselect", embName); + +export const graphLassoStartAction = () => + /* no change to crossfilter until a change fires */ + ({ type: "graph lasso start" }); + +export const graphLassoCancelAction = (embName) => + _graphAllAction("graph lasso cancel", embName); + +export const graphLassoDeselectAction = (embName) => + _graphAllAction("graph lasso cancel", embName); + +export const graphLassoEndAction = + (embName, polygon) => async (dispatch, getState) => { + const { obsCrossfilter: prevObsCrossfilter } = getState(); + + const selection = { + mode: "within-polygon", + polygon, + }; + const obsCrossfilter = await prevObsCrossfilter.select( + "emb", + embName, + selection + ); + + dispatch({ + type: "graph lasso end", + obsCrossfilter, + polygon, + }); + }; + +/* +Differential expression set selection +*/ +export const setCellSetFromSelection = (cellSetId) => (dispatch, getState) => { + const { obsCrossfilter } = getState(); + const selected = obsCrossfilter.allSelectedLabels(); + + dispatch({ + type: `store current cell selection as differential set ${cellSetId}`, + data: selected.length > 0 ? selected : null, + }); +}; diff --git a/client/src/actions/selection.ts b/client/src/actions/selection.ts deleted file mode 100644 index 0c4eace4..00000000 --- a/client/src/actions/selection.ts +++ /dev/null @@ -1,248 +0,0 @@ -/* -Action creators for selection -*/ -export const selectContinuousMetadataAction = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - type: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - query: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - range: any, - oldProps = {} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - const { obsCrossfilter: prevObsCrossfilter } = getState(); - - const selection = range - ? { - mode: "range", - lo: range[0], - hi: range[1], - inclusive: true, // [lo, hi] incluisve selection - } - : { mode: "all" }; - - const obsCrossfilter = await prevObsCrossfilter.select(...query, selection); - - dispatch({ - type, - obsCrossfilter, - range, - ...oldProps, - }); -}; - -export const selectCategoricalMetadataAction = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - type: any, // action type - // annotation category name - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labels: any, - // the label being selected/deselected - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - label: any, - // bool - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isSelected: any, - oldProps = {} - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - const { - obsCrossfilter: prevObsCrossfilter, - categoricalSelection, - } = getState(); - - const labelSelectionState = new Map(categoricalSelection[metadataField]); - labels.forEach( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (l: any) => labelSelectionState.has(l) || labelSelectionState.set(l, true) - ); - labelSelectionState.set(label, isSelected); - - const values = Array.from(labelSelectionState.keys()).filter((k) => - labelSelectionState.get(k) - ); - const selection = { - mode: "exact", - values, - }; - const obsCrossfilter = await prevObsCrossfilter.select( - "obs", - metadataField, - selection - ); - - dispatch({ - type, - obsCrossfilter, - metadataField, - labelSelectionState, - ...oldProps, - }); -}; - -export const selectCategoricalAllMetadataAction = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - type: any, // action type - // annotation category name - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labels: any, - // bool, select all or none - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isSelected: any, - oldProps = {} - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - const { - obsCrossfilter: prevObsCrossfilter, - categoricalSelection, - } = getState(); - - const labelSelectionState = new Map(categoricalSelection[metadataField]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - labels.forEach((label: any) => labelSelectionState.set(label, isSelected)); - - const selection = { mode: isSelected ? "all" : "none" }; - const obsCrossfilter = await prevObsCrossfilter.select( - "obs", - metadataField, - selection - ); - - dispatch({ - type, - obsCrossfilter, - metadataField, - labelSelectionState, - ...oldProps, - }); -}; - -/** - ** Graph selection-related actions - **/ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const graphBrushStartAction = () => - /* no change to crossfilter until a change fires */ - ({ type: "graph brush start" }); - -const _graphBrushWithinRectAction = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - type: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - embName: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - brushCoords: any - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -) => async (dispatch: any, getState: any) => { - const { obsCrossfilter: prevObsCrossfilter } = getState(); - - const selection = { mode: "within-rect", ...brushCoords }; - const obsCrossfilter = await prevObsCrossfilter.select( - "emb", - embName, - selection - ); - - dispatch({ - type, - obsCrossfilter, - brushCoords, - }); -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const _graphAllAction = (type: any, embName: any) => async ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - const { obsCrossfilter: prevObsCrossfilter } = getState(); - - const obsCrossfilter = await prevObsCrossfilter.select("emb", embName, { - mode: "all", - }); - - dispatch({ - type, - obsCrossfilter, - }); -}; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphBrushChangeAction = (embName: any, brushCoords: any) => - _graphBrushWithinRectAction("graph brush change", embName, brushCoords); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphBrushEndAction = (embName: any, brushCoords: any) => - _graphBrushWithinRectAction("graph brush end", embName, brushCoords); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphBrushCancelAction = (embName: any) => - _graphAllAction("graph brush cancel", embName); -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphBrushDeselectAction = (embName: any) => - _graphAllAction("graph brush deselect", embName); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const graphLassoStartAction = () => - /* no change to crossfilter until a change fires */ - ({ type: "graph lasso start" }); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphLassoCancelAction = (embName: any) => - _graphAllAction("graph lasso cancel", embName); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphLassoDeselectAction = (embName: any) => - _graphAllAction("graph lasso cancel", embName); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const graphLassoEndAction = (embName: any, polygon: any) => async ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - const { obsCrossfilter: prevObsCrossfilter } = getState(); - - const selection = { - mode: "within-polygon", - polygon, - }; - const obsCrossfilter = await prevObsCrossfilter.select( - "emb", - embName, - selection - ); - - dispatch({ - type: "graph lasso end", - obsCrossfilter, - polygon, - }); -}; - -/* -Differential expression set selection -*/ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const setCellSetFromSelection = (cellSetId: any) => ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { - const { obsCrossfilter } = getState(); - const selected = obsCrossfilter.allSelectedLabels(); - - dispatch({ - type: `store current cell selection as differential set ${cellSetId}`, - data: selected.length > 0 ? selected : null, - }); -}; diff --git a/client/src/actions/viewStack.ts b/client/src/actions/viewStack.js similarity index 63% rename from client/src/actions/viewStack.ts rename to client/src/actions/viewStack.js index 81f69335..8a7db485 100644 --- a/client/src/actions/viewStack.ts +++ b/client/src/actions/viewStack.js @@ -18,13 +18,7 @@ import { _userResetSubsetAnnoMatrix, } from "../util/stateManager/viewStackHelpers"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const clipAction = (min: any, max: any) => ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - dispatch: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getState: any -) => { +export const clipAction = (min, max) => (dispatch, getState) => { /* apply a clip to the current annoMatrix. By convention, the clip view is ALWAYS the top view. @@ -40,8 +34,7 @@ export const clipAction = (min: any, max: any) => ( }); }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const subsetAction = () => (dispatch: any, getState: any) => { +export const subsetAction = () => (dispatch, getState) => { /* Subset the annoMatrix to the current crossfilter selection by pushing a subset view. @@ -49,10 +42,8 @@ export const subsetAction = () => (dispatch: any, getState: any) => { By convention, a clip view is ALWAYS the top view, so if present, pop off and re-apply */ - const { - annoMatrix: prevAnnoMatrix, - obsCrossfilter: prevObsCrossfilter, - } = getState(); + const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevObsCrossfilter } = + getState(); const annoMatrix = _userSubsetAnnoMatrix( prevAnnoMatrix, prevObsCrossfilter.allSelectedMask() @@ -65,8 +56,7 @@ export const subsetAction = () => (dispatch: any, getState: any) => { }); }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const resetSubsetAction = () => (dispatch: any, getState: any) => { +export const resetSubsetAction = () => (dispatch, getState) => { /* Reset the annoMatrix to all data. Because we may have multiple views stacked, we pop them all. By convention, any clip transformation will diff --git a/client/src/annoMatrix/annoMatrix.ts b/client/src/annoMatrix/annoMatrix.js similarity index 58% rename from client/src/annoMatrix/annoMatrix.ts rename to client/src/annoMatrix/annoMatrix.js index 1c2765a3..1ed90995 100644 --- a/client/src/annoMatrix/annoMatrix.ts +++ b/client/src/annoMatrix/annoMatrix.js @@ -2,9 +2,6 @@ import { Dataframe, IdentityInt32Index, dataframeMemo, - LabelType, - DataframeValue, - DataframeValueArray, } from "../util/dataframe"; import { _getColumnDimensionNames, @@ -13,71 +10,13 @@ import { _getWritableColumns, } from "./schema"; import { indexEntireSchema } from "../util/stateManager/schemaHelpers"; -import { - _whereCacheGet, - _whereCacheMerge, - WhereCache, - WhereCacheColumnLabels, -} from "./whereCache"; +import { _whereCacheGet, _whereCacheMerge } from "./whereCache"; import _shallowClone from "./clone"; -import { _queryValidate, _queryCacheKey, Query } from "./query"; -import { GCHints } from "../common/types/entities"; -import { - AnnotationColumnSchema, - Category, - Field, - EmbeddingSchema, - Schema, - ArraySchema, - RawSchema, -} from "../common/types/schema"; -import { LabelArray } from "../util/dataframe/types"; -import { LabelIndexBase } from "../util/dataframe/labelIndex"; +import { _queryValidate, _queryCacheKey } from "./query"; const _dataframeCache = dataframeMemo(128); -interface Cache { - [Field.obs]: Dataframe; - [Field.var]: Dataframe; - [Field.emb]: Dataframe; - [Field.X]: Dataframe; -} - -interface PendingLoad { - [Field.obs]: { [key: string]: Promise }; - [Field.var]: { [key: string]: Promise }; - [Field.emb]: { [key: string]: Promise }; - [Field.X]: { [key: string]: Promise }; -} - -export interface UserFlags { - isUserSubsetView?: boolean; - isEmbSubsetView?: boolean; -} - -export default abstract class AnnoMatrix { - public isView: boolean; - - public nObs: number; - - public nVar: number; - - public rowIndex: LabelIndexBase; - - public schema: Schema; - - public userFlags: UserFlags; - - public viewOf: AnnoMatrix; - - public _cache: Cache; - - private _pendingLoad: PendingLoad; - - private _whereCache: WhereCache; - - private _gcInfo: Map; - +export default class AnnoMatrix { /* Abstract base class for all AnnoMatrix objects. This class provides a proxy to the annotated matrix data authoritatively served by the server/back-end. @@ -108,19 +47,14 @@ export default abstract class AnnoMatrix { subset(annoMatrix, rowLabels) -> annoMatrix etc. */ - static fields(): Field[] { + static fields() { /* return the fields present in the AnnoMatrix instance. */ - return [Field.obs, Field.var, Field.emb, Field.X]; + return ["obs", "var", "emb", "X"]; } - constructor( - schema: RawSchema, - nObs: number, - nVar: number, - rowIndex: LabelIndexBase | null = null - ) { + constructor(schema, nObs, nVar, rowIndex = null) { /* Private constructor - this is an abstract base class. Do not use. */ @@ -136,7 +70,7 @@ export default abstract class AnnoMatrix { * rowIndex - a rowIndex shared by all data on this view (ie, the list of cells). The row index labels are as defined by the base dataset from the server. * isView - true if this is a view, false if not. - * viewOf - pointer to parent annomatrix if a view, self if not a view. + * viewOf - pointer to parent annomatrix if a view, undefined/null if not a view. * userFlags - container for any additional state a user of this API wants to hang off of an annoMatrix, and have propagated by the (shallow) cloning protocol. */ @@ -145,17 +79,17 @@ export default abstract class AnnoMatrix { this.nVar = nVar; this.rowIndex = rowIndex || new IdentityInt32Index(nObs); this.isView = false; - this.viewOf = this; + this.viewOf = undefined; this.userFlags = {}; /* - Private instance variables. + Private instance variables. - These are caches - lazily loaded. The only guarantee is that if they - are loaded, they will conform to the schema & dimensionality constraints. + These are caches - lazily loaded. The only guarantee is that if they + 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 = { obs: Dataframe.empty(this.rowIndex), var: Dataframe.empty(this.rowIndex), @@ -168,14 +102,14 @@ export default abstract class AnnoMatrix { emb: {}, X: {}, }; - this._whereCache = {} as WhereCache; + this._whereCache = {}; this._gcInfo = new Map(); } /** ** Schema helper/accessors **/ - getMatrixColumns(field: Field): string[] { + getMatrixColumns(field) { /* Return array of column names in the field. ONLY supported on the obs, var and emb fields. X currently unimplemented and will throw. @@ -188,7 +122,7 @@ export default abstract class AnnoMatrix { } // eslint-disable-next-line class-methods-use-this -- need to be able to call this on instances - getMatrixFields(): Field[] { + getMatrixFields() { /* Return array of fields in this annoMatrix. Currently hard-wired to return: ["X", "obs", "var", "emb"]. @@ -198,7 +132,7 @@ export default abstract class AnnoMatrix { return AnnoMatrix.fields(); } - getColumnSchema(field: Field, col: LabelType): ArraySchema { + getColumnSchema(field, col) { /* Return the schema for the field & column ,eg, @@ -210,7 +144,7 @@ export default abstract class AnnoMatrix { return _getColumnSchema(this.schema, field, col); } - getColumnDimensions(field: Field, col: LabelType): LabelArray | undefined { + getColumnDimensions(field, col) { /* Return the dimensions on this field / column. For most fields, which are 1D, this just return the column name. Multi-dimensional columns, such as embeddings, @@ -228,19 +162,19 @@ export default abstract class AnnoMatrix { /** ** General utility methods **/ - base(): AnnoMatrix { + base() { /* return the base of view, or `this` if not a view. */ - let annoMatrix = this._getViewOf(); - while (annoMatrix.isView) annoMatrix = annoMatrix._getViewOf(); + let annoMatrix = this; + while (annoMatrix.isView) annoMatrix = annoMatrix.viewOf; return annoMatrix; } /** ** Load / read interfaces **/ - fetch(field: Field, q: Query | Query[]): Promise { + fetch(field, q) { /* Return the given query on a single matrix field as a single dataframe. Currently supports ONLY full column query. @@ -269,7 +203,7 @@ export default abstract class AnnoMatrix { 1. Fetch the "n_genes" column the "obs": const df = await fetch("obs", "n_genes") - console.log("Largest number of genes is: ", df.summarizeContinuous().max); + console.log("Largest number of genes is: ", df.summarize().max); 2. Fetch two separate columns from obs. Returns a single dataframe containing the columns: @@ -297,7 +231,7 @@ export default abstract class AnnoMatrix { return this._fetch(field, q); } - prefetch(field: Field, q: Query): void { + prefetch(field, q) { /* Start a data fetch & cache fill. Identical to fetch() except it does not return a value. @@ -306,6 +240,7 @@ export default abstract class AnnoMatrix { overall component rendering latency. */ this._fetch(field, q); + return undefined; } /** @@ -326,172 +261,176 @@ export default abstract class AnnoMatrix { ** The actual implementation is in the sub-classes, which MUST override these. **/ - /* - Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix. - Typical use is to add a new user-created label to a user-created obs categorical - annotation. + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + addObsAnnoCategory(col, category) { + /* + Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix. + Typical use is to add a new user-created label to a user-created obs categorical + annotation. - Will throw column does not exist or is not writable. + Will throw column does not exist or is not writable. - Example: + Example: - addObsAnnoCategory("my cell type", "left toenail") -> AnnoMatrix - - */ - abstract addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix; - - /* - Remove a category value from an obs column, reassign any obs having that value - to the 'unassignedCategory' value, and return a promise for a new AnnoMatrix. - Typical use is to remove a user-created label from a user-created obs categorical - annotation. - - Will throw column does not exist or is not writable. - - An `unassignedCategory` value must be provided, for assignment to any obs/cells - that had the now-delete category label as their value. - - Example: - await removeObsAnnoCategory("my-tissue-type", "right earlobe", "unassigned") -> AnnoMatrix - - NOTE: method is async as it may need to fetch data to provide the reassignment. - */ - abstract removeObsAnnoCategory( - col: LabelType, - category: Category, - unassignedCategory: string - ): Promise; - - /* - Drop an entire writable column, eg a user-created obs annotation. Typical use - is to provide the "Delete Category" implementation. Returns the new AnnoMatrix. - Will throw if not a writable annotation. - - Will throw column does not exist or is not writable. - - Example: - - dropObsColumn("old annotations") -> AnnoMatrix - */ - abstract dropObsColumn(col: LabelType): AnnoMatrix; - - /* - Add a new writable OBS annotation column, with the caller-specified schema, initial value - type and value. - - Value may be any one of: - * an array of values - * a primitive type, including null or undefined. - If an array, length must be the same as 'this.nObs', and constructor must equal 'Ctor'. - If a primitive, 'Ctor' will be used to create the initial value, which will be filled - with 'value'. - - Throws if the name specified in 'colSchema' duplicates an existing obs column. - - Returns a new AnnoMatrix. - - Examples: - - addObsColumn( - { name: "foo", type: "categorical", categories: "unassigned" }, - Array, - "unassigned" - ) -> AnnoMatrix - - */ - abstract addObsColumn( - colSchema: AnnotationColumnSchema, - Ctor: new (n: number) => T, - value: T - ): AnnoMatrix; - - /* - Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix. - - Will throw column does not exist or is not writable, or if 'newCol' is not unique. - - Example: - - renameObsColumn('cell type', 'old cell type') -> AnnoMatrix. - - */ - abstract renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix; - - /* - Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be - to set a group of cells to have a label on a user-created categorical annotation - (eg set all selected cells to have a label). - - NOTE: async method, as it may need to fetch. - - Will throw column does not exist or is not writable. - - Example: - await setObsColmnValues("flavor", [383, 400], "tasty") -> AnnoMtarix - */ - abstract setObsColumnValues( - col: LabelType, - obsLabels: Int32Array, - value: DataframeValue - ): Promise; - - /* - Set by value - all elements in the column with value 'oldValue' are set to 'newValue'. - Async method - returns a promise for a new AnnoMatrix. - - Typical use would be to set all labels of one value to another. - - Will throw column does not exist or is not writable. - - Example: - await resetObsColumnValues("my notes", "good", "not-good") -> AnnoMatrix + addObsAnnoCategory("my cell type", "left toenail") -> AnnoMatrix */ - abstract resetObsColumnValues( - col: LabelType, - oldValue: T, - newValue: T - ): Promise; + _subclassResponsibility(); + } - /* - Add a new obs embedding to the AnnoMatrix, with provided schema. - Returns a new annomatrix. - - Typical use will be to add a re-embedding that the server has calculated. - - Will throw if the column schema is invalid (eg, duplicate name). - */ - abstract addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix; - - getCacheKeys( - field: Field, - query: Query - ): WhereCacheColumnLabels | [undefined] { + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + async removeObsAnnoCategory(col, category, unassignedCategory) { /* -Return cache keys for columns associated with this query. May return -[unknown] if no keys are known (ie, nothing is or was cached). -*/ + Remove a category value from an obs column, reassign any obs having that value + to the 'unassignedCategory' value, and return a promise for a new AnnoMatrix. + Typical use is to remove a user-created label from a user-created obs categorical + annotation. + + Will throw column does not exist or is not writable. + + An `unassignedCategory` value must be provided, for assignment to any obs/cells + that had the now-delete category label as their value. + + Example: + await removeObsAnnoCategory("my-tissue-type", "right earlobe", "unassigned") -> AnnoMatrix + + NOTE: method is async as it may need to fetch data to provide the reassignment. + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + dropObsColumn(col) { + /* + Drop an entire writable column, eg a user-created obs annotation. Typical use + is to provide the "Delete Category" implementation. Returns the new AnnoMatrix. + Will throw if not a writable annotation. + + Will throw column does not exist or is not writable. + + Example: + + dropObsColumn("old annotations") -> AnnoMatrix + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + addObsColumn(colSchema, Ctor, value) { + /* + Add a new writable OBS annotation column, with the caller-specified schema, initial value + type and value. + + Value may be any one of: + * an array of values + * a primitive type, including null or undefined. + If an array, length must be the same as 'this.nObs', and constructor must equal 'Ctor'. + If a primitive, 'Ctor' will be used to create the initial value, which will be filled + with 'value'. + + Throws if the name specified in 'colSchema' duplicates an existing obs column. + + Returns a new AnnoMatrix. + + Examples: + + addObsColumn( + { name: "foo", type: "categorical", categories: "unassigned" }, + Array, + "unassigned" + ) -> AnnoMatrix + + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + renameObsColumn(oldCol, newCol) { + /* + Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix. + + Will throw column does not exist or is not writable, or if 'newCol' is not unique. + + Example: + + renameObsColumn('cell type', 'old cell type') -> AnnoMatrix. + + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + async setObsColumnValues(col, obsLabels, value) { + /* + Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be + to set a group of cells to have a label on a user-created categorical anntoation + (eg set all selected cells to have a label). + + NOTE: async method, as it may need to fetch. + + Will throw column does not exist or is not writable. + + Example: + await setObsColmnValues("flavor", [383, 400], "tasty") -> AnnoMtarix + + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + async resetObsColumnValues(col, oldValue, newValue) { + /* + Set by value - all elements in the column with value 'oldValue' are set to 'newValue'. + Async method - returns a promise for a new AnnoMatrix. + + Typical use would be to set all labels of one value to another. + + Will throw column does not exist or is not writable. + + Example: + await resetObsColumnValues("my notes", "good", "not-good") -> AnnoMatrix + + */ + _subclassResponsibility(); + } + + // eslint-disable-next-line class-methods-use-this, no-unused-vars -- make sure subclass implements + addEmbedding(colSchema) { + /* + Add a new obs embedding to the AnnoMatrix, with provided schema. + Returns a new annomatrix. + + Typical use will be to add a re-embedding that the server has calculated. + + Will throw if the column schema is invalid (eg, duplicate name). + */ + _subclassResponsibility(); + } + + getCacheKeys(field, query) { + /* + Return cache keys for columns associated with this query. May return + [unknown] if no keys are known (ie, nothing is or was cached). + */ return _whereCacheGet(this._whereCache, this.schema, field, query); } /** ** Private interfaces below. **/ - _resolveCachedQueries(field: Field, queries: Query[]): LabelArray { + _resolveCachedQueries(field, queries) { return queries - .map((query: Query) => - // @ts-expect-error --- TODO revisit: - // `filter`: This expression is not callable. + .map((query) => _whereCacheGet(this._whereCache, this.schema, field, query).filter( - (cacheKey?: LabelType) => + (cacheKey) => cacheKey !== undefined && this._cache[field].hasCol(cacheKey) ) ) .flat(); } - async _fetch(field: Field, q: Query | Query[]): Promise { - if (!AnnoMatrix.fields().includes(field)) return Dataframe.empty(); + async _fetch(field, q) { + if (!AnnoMatrix.fields().includes(field)) return undefined; const queries = Array.isArray(q) ? q : [q]; queries.forEach(_queryValidate); @@ -502,7 +441,7 @@ Return cache keys for columns associated with this query. May return /* find any query not already cached */ const uncachedQueries = queries.filter((query) => _whereCacheGet(this._whereCache, this.schema, field, query).some( - (cacheKey?: LabelType) => + (cacheKey) => cacheKey === undefined || !this._cache[field].hasCol(cacheKey) ) ); @@ -511,19 +450,15 @@ Return cache keys for columns associated with this query. May return if (uncachedQueries.length > 0) { await Promise.all( uncachedQueries.map((query) => - this._getPendingLoad( - field, - query, - async (_field: Field, _query: Query): Promise => { - /* fetch, then index. _doLoad is subclass interface */ - const [whereCacheUpdate, df] = await this._doLoad(_field, _query); - this._cache[_field] = this._cache[_field].withColsFrom(df); - this._whereCache = _whereCacheMerge( - this._whereCache, - whereCacheUpdate - ); - } - ) + this._getPendingLoad(field, query, async (_field, _query) => { + /* fetch, then index. _doLoad is subclass interface */ + const [whereCacheUpdate, df] = await this._doLoad(_field, _query); + this._cache[_field] = this._cache[_field].withColsFrom(df); + this._whereCache = _whereCacheMerge( + this._whereCache, + whereCacheUpdate + ); + }) ) ); } @@ -537,11 +472,7 @@ Return cache keys for columns associated with this query. May return return response; } - async _getPendingLoad( - field: Field, - query: Query, - fetchFn: (_field: Field, _query: Query) => Promise - ): Promise { + async _getPendingLoad(field, query, fetchFn) { /* Given a query on a field, ensure that we only have a single outstanding fetch at any given time. If multiple requests occur while a fetch is @@ -562,22 +493,9 @@ Return cache keys for columns associated with this query. May return return this._pendingLoad[field][key]; } - abstract _doLoad( - field: Field, - query: Query - ): Promise<[WhereCache | null, Dataframe]>; - - /** - * Determines viewOf for this annoMatrix. - * - * @internal - * @returns - parent annoMatrix if this annoMatrix is a view, otherwise this annoMatrix if it's not a view. - */ - _getViewOf(): AnnoMatrix { - if (this.isView) { - return this.viewOf; - } - return this; + // eslint-disable-next-line class-methods-use-this -- make sure subclass implements + async _doLoad() { + _subclassResponsibility(); } /** @@ -609,21 +527,20 @@ Return cache keys for columns associated with this query. May return 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. */ - _gcField(field: Field, isHot: boolean, pinnedColumns: LabelArray): void { - const maxColumns = isHot ? 256 : 10; + _gcField(field, isHot, pinnedColumns) { + const maxColumns = isHot ? 256 : 10; // maybe to aggressive? + const cache = this._cache[field]; if (cache.colIndex.size() < maxColumns) return; // trivial rejection const candidates = cache.colIndex .labels() - // @ts-expect-error --- TODO revisit: - // `col`: Argument of type 'LabelType' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'. - .filter((col: LabelType) => !pinnedColumns.includes(col)); + .filter((col) => !pinnedColumns.includes(col)); const excessCount = candidates.length + pinnedColumns.length - maxColumns; if (excessCount > 0) { const { _gcInfo } = this; - candidates.sort((a: LabelType, b: LabelType) => { + candidates.sort((a, b) => { let atime = _gcInfo.get(_columnCacheKey(field, a)); if (atime === undefined) atime = 0; @@ -640,49 +557,41 @@ Return cache keys for columns associated with this query. May return // ", " // )}]` // ); - // @ts-expect-error --- TODO revisit: - // `reduce`: This expression is not callable. this._cache[field] = toDrop.reduce( - (df: Dataframe, col: LabelType) => df.dropCol(col), + (df, col) => df.dropCol(col), this._cache[field] ); - toDrop.forEach((col: LabelType) => - _gcInfo.delete(_columnCacheKey(field, col)) - ); + toDrop.forEach((col) => _gcInfo.delete(_columnCacheKey(field, col))); } } - _gcFetchCleanup(field: Field, pinnedColumns: LabelArray): void { + _gcFetchCleanup(field, pinnedColumns) { /* Called during data load/fetch. By definition, this is 'hot', so we only want to gc X. */ - if (field === Field.X) { + if (field === "X") { this._gcField( field, true, - // @ts-expect-error --- TODO revisit: - // Property 'concat' does not exist on type 'LabelArray'. pinnedColumns.concat(_getWritableColumns(this.schema, field)) ); } } - _gc(hints: GCHints): void { + _gc(hints) { /* Called from middleware, or elsewhere. isHot is true if we are in the active store, or false if we are in some other context (eg, history state). */ const { isHot } = hints; - const candidateFields = isHot - ? [Field.X] - : [Field.X, Field.emb, Field.var, Field.obs]; + const candidateFields = isHot ? ["X"] : ["X", "emb", "var", "obs"]; candidateFields.forEach((field) => this._gcField(field, isHot, _getWritableColumns(this.schema, field)) ); } - _gcUpdateStats(field: Field, dataframe: Dataframe): void { + _gcUpdateStats(field, dataframe) { /* called each time a query is performed, allowing the gc to update any bookkeeping information. Currently, this is just a simple last-fetched timestamp, stored @@ -691,7 +600,7 @@ Return cache keys for columns associated with this query. May return const cols = dataframe.colIndex.labels(); const { _gcInfo } = this; const now = Date.now(); - cols.forEach((c: LabelType) => { + cols.forEach((c) => { _gcInfo.set(_columnCacheKey(field, c), now); }); } @@ -708,7 +617,7 @@ Return cache keys for columns associated with this query. May return Do not override _clone(); **/ - _cloneDeeper(clone: AnnoMatrix): AnnoMatrix { + _cloneDeeper(clone) { clone._cache = _shallowClone(this._cache); clone._gcInfo = new Map(); clone._pendingLoad = { @@ -720,7 +629,7 @@ Return cache keys for columns associated with this query. May return return clone; } - _clone(): AnnoMatrix { + _clone() { const clone = _shallowClone(this); this._cloneDeeper(clone); Object.seal(clone); @@ -731,6 +640,11 @@ Return cache keys for columns associated with this query. May return /* private utility functions below */ -function _columnCacheKey(field: Field, column: LabelType): string { +function _columnCacheKey(field, column) { return `${field}/${column}`; } + +function _subclassResponsibility() { + /* protect against bugs in subclass */ + throw new Error("subclass failed to implement required method"); +} diff --git a/client/src/annoMatrix/clone.ts b/client/src/annoMatrix/clone.js similarity index 70% rename from client/src/annoMatrix/clone.ts rename to client/src/annoMatrix/clone.js index 11f689ce..97cad4b5 100644 --- a/client/src/annoMatrix/clone.ts +++ b/client/src/annoMatrix/clone.js @@ -1,7 +1,6 @@ /* Shallow clone an object, correctly handling prototype */ - -export default function _shallowClone(orig: T): T { +export default function _shallowClone(orig) { return Object.assign(Object.create(Object.getPrototypeOf(orig)), orig); } diff --git a/client/src/annoMatrix/crossfilter.ts b/client/src/annoMatrix/crossfilter.js similarity index 64% rename from client/src/annoMatrix/crossfilter.ts rename to client/src/annoMatrix/crossfilter.js index d9948104..446688c0 100644 --- a/client/src/annoMatrix/crossfilter.ts +++ b/client/src/annoMatrix/crossfilter.js @@ -9,94 +9,56 @@ AnnoMatrix stay in sync: */ import Crossfilter from "../util/typedCrossfilter"; import { _getColumnSchema } from "./schema"; -import { - AnnotationColumnSchema, - Field, - EmbeddingSchema, -} from "../common/types/schema"; -import AnnoMatrix from "./annoMatrix"; -import { - Dataframe, - DataframeValue, - DataframeValueArray, - LabelType, -} from "../util/dataframe"; -import { Query } from "./query"; -import { TypedArray } from "../common/types/arraytypes"; -import { LabelArray } from "../util/dataframe/types"; -type ObsDimensionParams = - | [string, DataframeValueArray, DataframeValueArray] - | [string, DataframeValueArray] - | [string, DataframeValueArray, Int32ArrayConstructor] - | [string, DataframeValueArray, Float32ArrayConstructor]; - -function _dimensionNameFromDf(field: Field, df: Dataframe): string { +function _dimensionNameFromDf(field, df) { const colNames = df.colIndex.labels(); return _dimensionName(field, colNames); } -function _dimensionName( - field: Field, - colNames: LabelType | LabelArray -): string { +function _dimensionName(field, colNames) { if (!Array.isArray(colNames)) return `${field}/${colNames}`; return `${field}/${colNames.join(":")}`; } export default class AnnoMatrixObsCrossfilter { - annoMatrix: AnnoMatrix; - - obsCrossfilter: Crossfilter; - - constructor( - annoMatrix: AnnoMatrix, - _obsCrossfilter: Crossfilter | null = null - ) { + constructor(annoMatrix, _obsCrossfilter = null) { this.annoMatrix = annoMatrix; this.obsCrossfilter = _obsCrossfilter || new Crossfilter(annoMatrix._cache.obs); this.obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs); } - size(): number { + size() { return this.obsCrossfilter.size(); } /** - Managing the associated annoMatrix. These wrappers are necessary to + Managing the associated annoMatrix. These wrappers are necessary to make coordinated changes to BOTH the crossfilter and annoMatrix, and ensure that all state stays synchronized. See API documentation in annoMatrix.js. **/ - addObsColumn( - colSchema: AnnotationColumnSchema, - Ctor: new (n: number) => T, - value: T - ): AnnoMatrixObsCrossfilter { + addObsColumn(colSchema, Ctor, value) { const annoMatrix = this.annoMatrix.addObsColumn(colSchema, Ctor, value); const obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - dropObsColumn(col: LabelType): AnnoMatrixObsCrossfilter { + dropObsColumn(col) { const annoMatrix = this.annoMatrix.dropObsColumn(col); let { obsCrossfilter } = this; - const dimName = _dimensionName(Field.obs, col); + const dimName = _dimensionName("obs", col); if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); } return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - renameObsColumn( - oldCol: LabelType, - newCol: LabelType - ): AnnoMatrixObsCrossfilter { + renameObsColumn(oldCol, newCol) { const annoMatrix = this.annoMatrix.renameObsColumn(oldCol, newCol); - const oldDimName = _dimensionName(Field.obs, oldCol); - const newDimName = _dimensionName(Field.obs, newCol); + const oldDimName = _dimensionName("obs", oldCol); + const newDimName = _dimensionName("obs", newCol); let { obsCrossfilter } = this; if (obsCrossfilter.hasDimension(oldDimName)) { obsCrossfilter = obsCrossfilter.renameDimension(oldDimName, newDimName); @@ -104,12 +66,9 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - addObsAnnoCategory( - col: LabelType, - category: string - ): AnnoMatrixObsCrossfilter { + addObsAnnoCategory(col, category) { const annoMatrix = this.annoMatrix.addObsAnnoCategory(col, category); - const dimName = _dimensionName(Field.obs, col); + const dimName = _dimensionName("obs", col); let { obsCrossfilter } = this; if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); @@ -117,17 +76,13 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - async removeObsAnnoCategory( - col: LabelType, - category: string, - unassignedCategory: string - ): Promise { + async removeObsAnnoCategory(col, category, unassignedCategory) { const annoMatrix = await this.annoMatrix.removeObsAnnoCategory( col, category, unassignedCategory ); - const dimName = _dimensionName(Field.obs, col); + const dimName = _dimensionName("obs", col); let { obsCrossfilter } = this; if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); @@ -135,17 +90,13 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - async setObsColumnValues( - col: LabelType, - rowLabels: Int32Array, - value: DataframeValue - ): Promise { + async setObsColumnValues(col, rowLabels, value) { const annoMatrix = await this.annoMatrix.setObsColumnValues( col, rowLabels, value ); - const dimName = _dimensionName(Field.obs, col); + const dimName = _dimensionName("obs", col); let { obsCrossfilter } = this; if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); @@ -153,17 +104,13 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - async resetObsColumnValues( - col: LabelType, - oldValue: T, - newValue: T - ): Promise { + async resetObsColumnValues(col, oldValue, newValue) { const annoMatrix = await this.annoMatrix.resetObsColumnValues( col, oldValue, newValue ); - const dimName = _dimensionName(Field.obs, col); + const dimName = _dimensionName("obs", col); let { obsCrossfilter } = this; if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); @@ -171,25 +118,23 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - addEmbedding(colSchema: EmbeddingSchema): AnnoMatrixObsCrossfilter { + addEmbedding(colSchema) { const annoMatrix = this.annoMatrix.addEmbedding(colSchema); return new AnnoMatrixObsCrossfilter(annoMatrix, this.obsCrossfilter); } /** * Drop the crossfilter dimension. Do not change the annoMatrix. Useful when we - * want to stop tracking 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. */ - dropDimension(field: Field, query: Query): AnnoMatrixObsCrossfilter { + dropDimension(field, query) { const { annoMatrix } = this; let { obsCrossfilter } = this; const keys = annoMatrix .getCacheKeys(field, query) - // @ts-expect-error ts-migrate --- suppressing TS defect (https://github.com/microsoft/TypeScript/issues/44373). - // Compiler is complaining that expression is not callable on array union types. Remove suppression once fixed. - .filter((k?: string | number) => k !== undefined); - const dimName = _dimensionName(field, keys as string[]); + .filter((k) => k !== undefined); + const dimName = _dimensionName(field, keys); if (obsCrossfilter.hasDimension(dimName)) { obsCrossfilter = obsCrossfilter.delDimension(dimName); } @@ -201,12 +146,7 @@ export default class AnnoMatrixObsCrossfilter { are just wrappers to lazy create indices. **/ - async select( - field: Field, - query: Query, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from util/typedCrossfilter - spec: any - ): Promise { + async select(field, query, spec) { const { annoMatrix } = this; let { obsCrossfilter } = this; @@ -219,9 +159,7 @@ export default class AnnoMatrixObsCrossfilter { // grab the data, so we can grab the index. const df = await annoMatrix.fetch(field, query); - if (!df) { - throw new Error("Dataframe cannot be `undefined`"); - } + const dimName = _dimensionNameFromDf(field, df); if (!obsCrossfilter.hasDimension(dimName)) { // lazy index generation - add dimension when first used @@ -238,26 +176,23 @@ export default class AnnoMatrixObsCrossfilter { return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - selectAll(): AnnoMatrixObsCrossfilter { + selectAll() { /* Select all on any dimension in this field. */ const { annoMatrix } = this; const currentDims = this.obsCrossfilter.dimensionNames(); - const obsCrossfilter = currentDims.reduce( - (xfltr, dim) => xfltr.select(dim, { mode: "all" }), - this.obsCrossfilter - ); + const obsCrossfilter = currentDims.reduce((xfltr, dim) => xfltr.select(dim, { mode: "all" }), this.obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); } - countSelected(): number { + countSelected() { /* if no data yet indexed in the crossfilter, just say everything is selected */ if (this.obsCrossfilter.size() === 0) return this.annoMatrix.nObs; return this.obsCrossfilter.countSelected(); } - allSelectedMask(): Uint8Array { + allSelectedMask() { /* if no data yet indexed in the crossfilter, just say everything is selected */ if ( this.obsCrossfilter.size() === 0 || @@ -269,7 +204,7 @@ export default class AnnoMatrixObsCrossfilter { return this.obsCrossfilter.allSelectedMask(); } - allSelectedLabels(): LabelArray { + allSelectedLabels() { /* if no data yet indexed in the crossfilter, just say everything is selected */ if ( this.obsCrossfilter.size() === 0 || @@ -283,18 +218,12 @@ export default class AnnoMatrixObsCrossfilter { return index.labels(); } - fillByIsSelected( - array: A, - selectedValue: A[0], - deselectedValue: A[0] - ): A { + fillByIsSelected(array, selectedValue, deselectedValue) { /* if no data yet indexed in the crossfilter, just say everything is selected */ if ( this.obsCrossfilter.size() === 0 || this.obsCrossfilter.dimensionNames().length === 0 ) { - // @ts-expect-error ts-migrate --- TODO revisit: - // Type 'Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array' is not assignable to type 'A'... return array.fill(selectedValue); } return this.obsCrossfilter.fillByIsSelected( @@ -308,35 +237,25 @@ export default class AnnoMatrixObsCrossfilter { ** Private below **/ - _addObsCrossfilterDimension( - annoMatrix: AnnoMatrix, - obsCrossfilter: Crossfilter, - field: Field, - df: Dataframe - ): Crossfilter { + _addObsCrossfilterDimension(annoMatrix, obsCrossfilter, field, df) { if (field === "var") return obsCrossfilter; const dimName = _dimensionNameFromDf(field, df); const dimParams = this._getObsDimensionParams(field, df); obsCrossfilter = obsCrossfilter.setData(annoMatrix._cache.obs); - // @ts-expect-error ts-migrate --- TODO revisit: - // `...dimParams`: A spread argument must either have a tuple type or be passed to a rest parameter. obsCrossfilter = obsCrossfilter.addDimension(dimName, ...dimParams); return obsCrossfilter; } - _getColumnBaseType(field: Field, col: LabelType): string { + _getColumnBaseType(field, col) { /* Look up the primitive type for this field/col */ const colSchema = _getColumnSchema(this.annoMatrix.schema, field, col); return colSchema.type; } - _getObsDimensionParams( - field: Field, - df: Dataframe - ): ObsDimensionParams | undefined { + _getObsDimensionParams(field, df) { /* return the crossfilter dimensiontype type and params for this field/dataframe */ - if (field === Field.emb) { + if (field === "emb") { /* assumed to be 2D */ return ["spatial", df.icol(0).asArray(), df.icol(1).asArray()]; } @@ -344,8 +263,6 @@ export default class AnnoMatrixObsCrossfilter { /* assumed to be 1D */ const col = df.icol(0); const colName = df.colIndex.getLabel(0); - // @ts-expect-error --- TODO revisit: - // `colName` Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'. Type 'undefined' is not assignable to type 'LabelType'. const type = this._getColumnBaseType(field, colName); if (type === "string" || type === "categorical" || type === "boolean") { return ["enum", col.asArray()]; diff --git a/client/src/annoMatrix/fetchHelpers.js b/client/src/annoMatrix/fetchHelpers.js new file mode 100644 index 00000000..73b01cf2 --- /dev/null +++ b/client/src/annoMatrix/fetchHelpers.js @@ -0,0 +1,25 @@ +export { doBinaryRequest, doFetch } from "../util/actionHelpers"; + +/* double URI encode - needed for query-param filters */ +export function _dubEncURIComp(s) { + return encodeURIComponent(encodeURIComponent(s)); +} + +/* currently unused, consider deleting */ +export function _fetchResult(promise) { + let _status = "pending"; + const res = promise.then( + (r) => { + _status = "success"; + return r; + }, + (e) => { + _status = "error"; + throw e; + } + ); + + res.status = () => _status; + + return res; +} diff --git a/client/src/annoMatrix/fetchHelpers.ts b/client/src/annoMatrix/fetchHelpers.ts deleted file mode 100644 index 27d2198f..00000000 --- a/client/src/annoMatrix/fetchHelpers.ts +++ /dev/null @@ -1,28 +0,0 @@ -export { doBinaryRequest, doFetch } from "../util/actionHelpers"; - -/* double URI encode - needed for query-param filters */ -export function _dubEncURIComp(s: string | number | boolean): string { - return encodeURIComponent(encodeURIComponent(s)); -} - -/* currently unused, consider deleting */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function _fetchResult(promise: any) { - let _status = "pending"; - const res = promise.then( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (r: any) => { - _status = "success"; - return r; - }, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (e: any) => { - _status = "error"; - throw e; - } - ); - - res.status = () => _status; - - return res; -} diff --git a/client/src/annoMatrix/index.ts b/client/src/annoMatrix/index.js similarity index 100% rename from client/src/annoMatrix/index.ts rename to client/src/annoMatrix/index.js diff --git a/client/src/annoMatrix/loader.ts b/client/src/annoMatrix/loader.js similarity index 65% rename from client/src/annoMatrix/loader.ts rename to client/src/annoMatrix/loader.js index 1480132f..7eb89065 100644 --- a/client/src/annoMatrix/loader.ts +++ b/client/src/annoMatrix/loader.js @@ -2,47 +2,31 @@ import { doBinaryRequest, doFetch } from "./fetchHelpers"; import { matrixFBSToDataframe } from "../util/stateManager/matrix"; import { _getColumnSchema } from "./schema"; import { - addObsAnnoCategory, addObsAnnoColumn, - addObsLayout, - removeObsAnnoCategory, removeObsAnnoColumn, + addObsAnnoCategory, + removeObsAnnoCategory, + addObsLayout, } from "../util/stateManager/schemaHelpers"; -import { isAnyArray } from "../common/types/arraytypes"; -import { _whereCacheCreate, WhereCache } from "./whereCache"; +import { isArrayOrTypedArray } from "../util/typeHelpers"; +import { _whereCacheCreate } from "./whereCache"; import AnnoMatrix from "./annoMatrix"; import PromiseLimit from "../util/promiseLimit"; import { - _expectComplexQuery, _expectSimpleQuery, - _hashStringValues, - _urlEncodeComplexQuery, + _expectComplexQuery, _urlEncodeLabelQuery, - ComplexQuery, - Query, + _urlEncodeComplexQuery, + _hashStringValues, } from "./query"; import { normalizeResponse, normalizeWritableCategoricalSchema, } from "./normalize"; -import { - AnnotationColumnSchema, - Field, - EmbeddingSchema, - RawSchema, -} from "../common/types/schema"; -import { - Dataframe, - DataframeValue, - DataframeValueArray, - LabelType, -} from "../util/dataframe"; const promiseThrottle = new PromiseLimit(5); export default class AnnoMatrixLoader extends AnnoMatrix { - baseURL: string; - /* AnnoMatrix implementation which proxies to HTTP server using the CXG REST API. Used as the base (non-view) instance. @@ -53,7 +37,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { new AnnoMatrixLoader(serverBaseURL, schema) -> instance */ - constructor(baseURL: string, schema: RawSchema) { + constructor(baseURL, schema) { const { nObs, nVar } = schema.dataframe; super(schema, nObs, nVar); @@ -68,36 +52,24 @@ export default class AnnoMatrixLoader extends AnnoMatrix { /** ** Public. API described in base class. **/ - addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix { + addObsAnnoCategory(col, category) { /* Add a new category (aka label) to the schema for an obs column. */ - const colSchema = _getColumnSchema( - this.schema, - Field.obs, - col - ) as AnnotationColumnSchema; - _writableObsCategoryTypeCheck(colSchema); // throws on error + const colSchema = _getColumnSchema(this.schema, "obs", col); + _writableCategoryTypeCheck(colSchema); // throws on error const newAnnoMatrix = this._clone(); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, category); return newAnnoMatrix; } - async removeObsAnnoCategory( - col: LabelType, - category: string, - unassignedCategory: string - ): Promise { + async removeObsAnnoCategory(col, category, unassignedCategory) { /* Remove a single "category" (aka "label") from the data & schema of an obs column. */ - const colSchema = _getColumnSchema( - this.schema, - Field.obs, - col - ) as AnnotationColumnSchema; - _writableObsCategoryTypeCheck(colSchema); // throws on error + const colSchema = _getColumnSchema(this.schema, "obs", col); + _writableCategoryTypeCheck(colSchema); // throws on error const newAnnoMatrix = await this.resetObsColumnValues( col, @@ -112,16 +84,12 @@ export default class AnnoMatrixLoader extends AnnoMatrix { return newAnnoMatrix; } - dropObsColumn(col: LabelType): AnnoMatrix { + dropObsColumn(col) { /* drop column from field */ - const colSchema = _getColumnSchema( - this.schema, - Field.obs, - col - ) as AnnotationColumnSchema; - _writableObsCheck(colSchema); // throws on error + const colSchema = _getColumnSchema(this.schema, "obs", col); + _writableCheck(colSchema); // throws on error const newAnnoMatrix = this._clone(); newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col); @@ -129,11 +97,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { return newAnnoMatrix; } - addObsColumn( - colSchema: AnnotationColumnSchema, - Ctor: new (n: number) => T, - value: T - ): AnnoMatrix { + addObsColumn(colSchema, Ctor, value) { /* add a column to field, initializing with value. Value may be one of: @@ -144,7 +108,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { colSchema.writable = true; const colName = colSchema.name; if ( - _getColumnSchema(this.schema, Field.obs, colName) || + _getColumnSchema(this.schema, "obs", colName) || this._cache.obs.hasCol(colName) ) { throw new Error("column already exists"); @@ -152,7 +116,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { const newAnnoMatrix = this._clone(); let data; - if (isAnyArray(value)) { + if (isArrayOrTypedArray(value)) { if (value.constructor !== Ctor) throw new Error("Mismatched value array type"); if (value.length !== this.nObs) @@ -170,50 +134,35 @@ export default class AnnoMatrixLoader extends AnnoMatrix { return newAnnoMatrix; } - renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix { + renameObsColumn(oldCol, newCol) { /* Rename the obs oldColName to newColName. oldCol must be writable. */ - const oldColSchema = _getColumnSchema( - this.schema, - Field.obs, - oldCol - ) as AnnotationColumnSchema; - _writableObsCheck(oldColSchema); + const oldColSchema = _getColumnSchema(this.schema, "obs", oldCol); + _writableCheck(oldColSchema); // throws on error + const value = this._cache.obs.hasCol(oldCol) ? this._cache.obs.col(oldCol).asArray() : undefined; return this.dropObsColumn(oldCol).addObsColumn( { ...oldColSchema, - // @ts-expect-error ts-migrate --- TODO revisit: - // `name`: Type 'LabelType' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'. name: newCol, }, - // @ts-expect-error ts-migrate --- TODO revisit: - // `value`: Object is possibly 'undefined'. value.constructor, value ); } - async setObsColumnValues( - col: LabelType, - rowLabels: Int32Array, - value: DataframeValue - ): Promise { + async setObsColumnValues(col, rowLabels, value) { /* Set all rows identified by rowLabels to value. */ - const colSchema = _getColumnSchema( - this.schema, - Field.obs, - col - ) as AnnotationColumnSchema; - _writableObsCategoryTypeCheck(colSchema); // throws on error + const colSchema = _getColumnSchema(this.schema, "obs", col); + _writableCategoryTypeCheck(colSchema); // throws on error // ensure that we have the data in cache before we manipulate it - await this.fetch(Field.obs, col); + await this.fetch("obs", col); if (!this._cache.obs.hasCol(col)) throw new Error("Internal error - user annotation data missing"); @@ -221,7 +170,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { const data = this._cache.obs.col(col).asArray().slice(); for (let i = 0, len = rowIndices.length; i < len; i += 1) { const idx = rowIndices[i]; - if (idx === -1) throw new Error("Unknown row label"); + if (idx === undefined) throw new Error("Unknown row label"); data[idx] = value; } @@ -234,29 +183,19 @@ export default class AnnoMatrixLoader extends AnnoMatrix { return newAnnoMatrix; } - async resetObsColumnValues( - col: LabelType, - oldValue: T, - newValue: T - ): Promise { + async resetObsColumnValues(col, oldValue, newValue) { /* Set all rows with value 'oldValue' to 'newValue'. */ - const colSchema = _getColumnSchema( - this.schema, - Field.obs, - col - ) as AnnotationColumnSchema; - _writableObsCategoryTypeCheck(colSchema); // throws on error + const colSchema = _getColumnSchema(this.schema, "obs", col); + _writableCategoryTypeCheck(colSchema); // throws on error - // @ts-expect-error ts-migrate --- TODO revisit: - // `colSchema.categories`: Object is possibly 'undefined'. if (!colSchema.categories.includes(oldValue)) { throw new Error("unknown category"); } // ensure that we have the data in cache before we manipulate it - await this.fetch(Field.obs, col); + await this.fetch("obs", col); if (!this._cache.obs.hasCol(col)) throw new Error("Internal error - user annotation data missing"); @@ -274,12 +213,12 @@ export default class AnnoMatrixLoader extends AnnoMatrix { return newAnnoMatrix; } - addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix { + addEmbedding(colSchema) { /* add new layout to the obs embeddings */ const { name: colName } = colSchema; - if (_getColumnSchema(this.schema, Field.emb, colName)) { + if (_getColumnSchema(this.schema, "emb", colName)) { throw new Error("column already exists"); } @@ -291,10 +230,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { /** ** Private below **/ - async _doLoad( - field: Field, - query: Query - ): Promise<[WhereCache | null, Dataframe]> { + async _doLoad(field, query) { /* _doLoad - evaluates the query against the field. Returns: * whereCache update: column query map mapping the query to the column labels @@ -321,9 +257,8 @@ export default class AnnoMatrixLoader extends AnnoMatrix { default: throw new Error("Unknown field name"); } + const buffer = await promiseThrottle.priorityAdd(priority, doRequest); - // @ts-expect-error --- TODO revisit: - // `buffer`: Argument of type 'unknown' is not assignable to parameter of type 'ArrayBuffer | ArrayBuffer[]'. Type 'unknown' is not assignable to type 'ArrayBuffer[]'. let result = matrixFBSToDataframe(buffer); if (!result || result.isEmpty()) throw Error("Unknown field/col"); @@ -333,7 +268,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix { result.colIndex.labels() ); - result = normalizeResponse(field, this.schema, result); + result = normalizeResponse(field, query, this.schema, result); return [whereCacheUpdate, result]; } @@ -343,26 +278,20 @@ export default class AnnoMatrixLoader extends AnnoMatrix { Utility functions below */ -function _writableObsCheck(obsColSchema: AnnotationColumnSchema): void { - if (!obsColSchema?.writable) { +function _writableCheck(colSchema) { + if (!colSchema?.writable) { throw new Error("Unknown or readonly obs column"); } } -function _writableObsCategoryTypeCheck( - obsColSchema: AnnotationColumnSchema -): void { - _writableObsCheck(obsColSchema); - if (obsColSchema.type !== "categorical") { +function _writableCategoryTypeCheck(colSchema) { + _writableCheck(colSchema); + if (colSchema.type !== "categorical") { throw new Error("column must be categorical"); } } -function _embLoader( - baseURL: string, - _field: Field, - query: Query -): () => Promise { +function _embLoader(baseURL, _field, query) { _expectSimpleQuery(query); const urlBase = `${baseURL}layout/obs`; @@ -371,11 +300,7 @@ function _embLoader( return () => doBinaryRequest(url); } -function _obsOrVarLoader( - baseURL: string, - field: Field, - query: Query -): () => Promise { +function _obsOrVarLoader(baseURL, field, query) { _expectSimpleQuery(query); const urlBase = `${baseURL}annotations/${field}`; @@ -384,26 +309,19 @@ function _obsOrVarLoader( return () => doBinaryRequest(url); } -function _XLoader( - baseURL: string, - _field: Field, - query: Query -): () => Promise { +function _XLoader(baseURL, field, query) { _expectComplexQuery(query); - // Casting here as query is validated to be complex in _expectComplexQuery above. - const complexQuery = query as ComplexQuery; - - if ("where" in complexQuery) { + if (query.where) { const urlBase = `${baseURL}data/var`; - const urlQuery = _urlEncodeComplexQuery(complexQuery); + const urlQuery = _urlEncodeComplexQuery(query); const url = `${urlBase}?${urlQuery}`; return () => doBinaryRequest(url); } - if ("summarize" in complexQuery) { + if (query.summarize) { const urlBase = `${baseURL}summarize/var`; - const urlQuery = _urlEncodeComplexQuery(complexQuery); + const urlQuery = _urlEncodeComplexQuery(query); if (urlBase.length + urlQuery.length < 2000) { const url = `${urlBase}?${urlQuery}`; diff --git a/client/src/annoMatrix/middleware.ts b/client/src/annoMatrix/middleware.js similarity index 50% rename from client/src/annoMatrix/middleware.ts rename to client/src/annoMatrix/middleware.js index 07f9c0b4..d332b79a 100644 --- a/client/src/annoMatrix/middleware.ts +++ b/client/src/annoMatrix/middleware.js @@ -11,24 +11,16 @@ Undoable metareducer and the AnnoMatrix private API. It would be helpful to make the Undoable interface better factored. */ -import { Action, Dispatch, MiddlewareAPI } from "redux"; -import AnnoMatrix from "./annoMatrix"; -import { GCHints } from "../common/types/entities"; - -const annoMatrixGC = - (store: MiddlewareAPI) => - // GC middleware doesn't add any extra types to dispatch; it just executes GC and continues. - (next: Dispatch) => - (action: Action): Action => { - if (_itIsTimeForGC()) { - _doGC(store); - } - return next(action); - }; +const annoMatrixGC = (store) => (next) => (action) => { + if (_itIsTimeForGC()) { + _doGC(store); + } + return next(action); +}; let lastGCTime = 0; const InterGCDelayMS = 30 * 1000; // 30 seconds -function _itIsTimeForGC(): boolean { +function _itIsTimeForGC() { /* we don't want to run GC on every dispatch, so throttle it a bit. @@ -42,22 +34,17 @@ function _itIsTimeForGC(): boolean { return false; } -function _doGC(store: MiddlewareAPI): void { +function _doGC(store) { const state = store.getState(); // these should probably be a function imported from undoable.js, etc, as - // they have overly intimate knowledge of our reducers. + // they have overly intimiate knowledge of our reducers. const undoablePast = state["@@undoable/past"]; const undoableFuture = state["@@undoable/future"]; const undoableStack = undoablePast .concat(undoableFuture) - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from /reducers - .flatMap((snapshot: any) => - snapshot - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from /reducers - .filter((v: any) => v[0] === "annoMatrix") - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from /reducers - .map((v: any) => v[1]) + .flatMap((snapshot) => + snapshot.filter((v) => v[0] === "annoMatrix").map((v) => v[1]) ); const currentAnnoMatrix = state.annoMatrix; @@ -65,17 +52,15 @@ function _doGC(store: MiddlewareAPI): void { We want to identify those matrixes currently "hot", ie, linked from the current annoMatrix, as our current gc algo is more aggressive with those not hot. */ - const allAnnoMatrices = new Map( - undoableStack.map((m: AnnoMatrix) => [m, { isHot: false }]) + const allAnnoMatrices = new Map( + undoableStack.map((m) => [m, { isHot: false }]) ); let am = currentAnnoMatrix; - while (am?.isView) { + while (am) { allAnnoMatrices.set(am, { isHot: true }); am = am.viewOf; } - allAnnoMatrices.forEach((hints, annoMatrix: AnnoMatrix) => - annoMatrix._gc(hints) - ); + allAnnoMatrices.forEach((hints, annoMatrix) => annoMatrix._gc(hints)); } export default annoMatrixGC; diff --git a/client/src/annoMatrix/normalize.ts b/client/src/annoMatrix/normalize.js similarity index 83% rename from client/src/annoMatrix/normalize.ts rename to client/src/annoMatrix/normalize.js index a0018383..e9ccad29 100644 --- a/client/src/annoMatrix/normalize.ts +++ b/client/src/annoMatrix/normalize.js @@ -5,19 +5,8 @@ import { overflowCategoryLabel, globalConfig, } from "../globals"; -import { Dataframe, LabelType, DataframeColumn } from "../util/dataframe"; -import { - AnnotationColumnSchema, - ArraySchema, - Field, - Schema, -} from "../common/types/schema"; -export function normalizeResponse( - field: Field, - schema: Schema, - response: Dataframe -): Dataframe { +export function normalizeResponse(field, query, schema, response) { /** * There are a number of assumptions in the front-end about data typing and data * characteristics. This routine will normalize a server response dataframe @@ -42,15 +31,11 @@ export function normalizeResponse( */ // currently no data or schema normalization necessary for X or emb - if (field !== Field.obs && field !== Field.var) return response; + if (field !== "obs" && field !== "var") return response; const colLabels = response.colIndex.labels(); for (const colLabel of colLabels) { - const colSchema = _getColumnSchema( - schema, - field, - colLabel - ) as AnnotationColumnSchema; + const colSchema = _getColumnSchema(schema, field, colLabel); const isIndex = _isIndex(schema, field, colLabel); const { type, writable } = colSchema; @@ -74,7 +59,7 @@ export function normalizeResponse( return response; } -function castColumnToBoolean(df: Dataframe, label: LabelType): Dataframe { +function castColumnToBoolean(df, label) { const colData = df.col(label).asArray(); const newColData = new Array(colData.length); for (let i = 0; i < colData.length; i += 1) newColData[i] = !!colData[i]; @@ -82,16 +67,13 @@ function castColumnToBoolean(df: Dataframe, label: LabelType): Dataframe { return df; } -export function normalizeWritableCategoricalSchema( - colSchema: AnnotationColumnSchema, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - col: DataframeColumn -): ArraySchema { +export function normalizeWritableCategoricalSchema(colSchema, col) { /* Ensure all enum writable / categorical schema have a categories array, that the categories array contains all unique values in the data array, AND that the array is UI sorted. */ - const categorySet = new Set( + const categorySet = new Set( col.summarizeCategorical().categories.concat(colSchema.categories ?? []) ); if (!categorySet.has(unassignedCategoryLabel)) { @@ -101,19 +83,15 @@ export function normalizeWritableCategoricalSchema( return colSchema; } -export function normalizeCategorical( - df: Dataframe, - colLabel: LabelType, - colSchema: AnnotationColumnSchema -): Dataframe { +export function normalizeCategorical(df, colLabel, colSchema) { /* If writable, ensure schema matches data and we have an unassigned label - If not writable, ensure schema matches data and that we consolidate labels in excess of "top N" into an overflow labels. */ const { writable } = colSchema; const col = df.col(colLabel); + if (writable) { // writable (aka user) annotations normalizeWritableCategoricalSchema(colSchema, col); @@ -125,7 +103,7 @@ export function normalizeCategorical( // consolidate all categories from data and schema into a single list const colDataSummary = col.summarizeCategorical(); - const allCategories = new Set( + const allCategories = new Set( colDataSummary.categories.concat(colSchema.categories ?? []) ); diff --git a/client/src/annoMatrix/query.ts b/client/src/annoMatrix/query.js similarity index 63% rename from client/src/annoMatrix/query.ts rename to client/src/annoMatrix/query.js index f2a1b0ed..55017858 100644 --- a/client/src/annoMatrix/query.ts +++ b/client/src/annoMatrix/query.js @@ -1,52 +1,21 @@ import sha1 from "sha1"; import { _dubEncURIComp } from "./fetchHelpers"; -import { Field } from "../common/types/schema"; -import { LabelType } from "../util/dataframe"; /** * Query utilities, mostly for debugging support and validation. */ -export type ComplexQuery = SummarizeQuery | WhereQuery; - -export type Query = LabelType | ComplexQuery; - -interface SummarizeQuery { - summarize: SummarizeQueryTerm; -} - -interface SummarizeQueryTerm { - column: string; - field: string; - method: string; - values: string[]; -} - -interface WhereQuery { - where: WhereQueryTerm; -} - -interface WhereQueryTerm { - column: string; - field: string; - value: string; -} - -export function _expectSimpleQuery(query: Query): void { - if (typeof query === "object") throw new Error("expected simple query"); -} - /** * Normalize & error check the query. - * @param {Query} query - the query - * @returns {Query} - the normalized query + * @param {object | string} query - the query + * @returns {object | string} - the normalized query */ -export function _queryValidate(query: Query): Query { +export function _queryValidate(query) { if (typeof query !== "object") return query; - if ("where" in query && "summarize" in query) + if (query.where && query.summarize) throw new Error("query may not specify both where and summarize"); - if ("where" in query) { + if (query.where) { const { field: queryField, column: queryColumn, @@ -56,7 +25,7 @@ export function _queryValidate(query: Query): Query { throw new Error("Incomplete where query"); return query; } - if ("summarize" in query) { + if (query.summarize) { const { field: queryField, column: queryColumn, @@ -71,7 +40,11 @@ export function _queryValidate(query: Query): Query { throw new Error("query must specify one of where or summarize"); } -export function _expectComplexQuery(query: Query): void { +export function _expectSimpleQuery(query) { + if (typeof query === "object") throw new Error("expected simple query"); +} + +export function _expectComplexQuery(query) { if (typeof query !== "object") throw new Error("expected complex query"); } @@ -80,12 +53,12 @@ export function _expectComplexQuery(query: Query): void { * * @param {string} field * @param {string|object} query - * @returns {string} the key + * @returns the key */ -export function _queryCacheKey(field: Field, query: Query): string { +export function _queryCacheKey(field, query) { if (typeof query === "object") { // complex query - if ("where" in query) { + if (query.where) { const { field: queryField, column: queryColumn, @@ -93,7 +66,7 @@ export function _queryCacheKey(field: Field, query: Query): string { } = query.where; return `${field}/${queryField}/${queryColumn}/${queryValue}`; } - if ("summarize" in query) { + if (query.summarize) { const { method, field: queryField, @@ -111,34 +84,34 @@ export function _queryCacheKey(field: Field, query: Query): string { return `${field}/${query}`; } -function _urlEncodeWhereQuery(q: WhereQueryTerm): string { +function _urlEncodeWhereQuery(q) { const { field: queryField, column: queryColumn, value: queryValue } = q; return `${_dubEncURIComp(queryField)}:${_dubEncURIComp( queryColumn )}=${_dubEncURIComp(queryValue)}`; } -function _urlEncodeSummarizeQuery(q: SummarizeQueryTerm): string { +function _urlEncodeSummarizeQuery(q) { const { method, field, column, values } = q; const filter = values - .map((value: string) => _urlEncodeWhereQuery({ field, column, value })) + .map((value) => _urlEncodeWhereQuery({ field, column, value })) .join("&"); return `method=${method}&${filter}`; } -export function _urlEncodeComplexQuery(q: ComplexQuery): string { +export function _urlEncodeComplexQuery(q) { if (typeof q === "object") { - if ("where" in q) { + if (q.where) { return _urlEncodeWhereQuery(q.where); } - if ("summarize" in q) { + if (q.summarize) { return _urlEncodeSummarizeQuery(q.summarize); } } throw new Error("Unrecognized complex query type"); } -export function _urlEncodeLabelQuery(colKey: string, q: Query): string { +export function _urlEncodeLabelQuery(colKey, q) { if (!colKey) throw new Error("Unsupported query by name"); if (typeof q !== "string") throw new Error("Query must be a simple label."); return `${colKey}=${encodeURIComponent(q)}`; @@ -147,6 +120,7 @@ export function _urlEncodeLabelQuery(colKey: string, q: Query): string { /** * Generate the column key the server will send us for this query. */ -export function _hashStringValues(arrayOfString: string[]): string { - return sha1(arrayOfString.join("")); +export function _hashStringValues(arrayOfString) { + const hash = sha1(arrayOfString.join("")); + return hash; } diff --git a/client/src/annoMatrix/schema.ts b/client/src/annoMatrix/schema.js similarity index 56% rename from client/src/annoMatrix/schema.ts rename to client/src/annoMatrix/schema.js index 0224655e..745ddf6c 100644 --- a/client/src/annoMatrix/schema.ts +++ b/client/src/annoMatrix/schema.js @@ -1,54 +1,34 @@ /* Private helper functions related to schema */ -import { - AnnotationColumnSchema, - ArraySchema, - Field, - Schema, -} from "../common/types/schema"; -import { LabelArray, LabelType } from "../util/dataframe/types"; - -export function _getColumnSchema( - schema: Schema, - field: Field, - col: LabelType -): ArraySchema { +export function _getColumnSchema(schema, field, col) { /* look up the column definition */ switch (field) { - case Field.obs: + case "obs": if (typeof col === "object") throw new Error("unable to get column schema by query"); return schema.annotations.obsByName[col]; - case Field.var: + case "var": if (typeof col === "object") throw new Error("unable to get column schema by query"); return schema.annotations.varByName[col]; - case Field.emb: + case "emb": if (typeof col === "object") throw new Error("unable to get column schema by query"); return schema.layout.obsByName[col]; - case Field.X: + case "X": return schema.dataframe; default: throw new Error(`unknown field name: ${field}`); } } -export function _isIndex( - schema: Schema, - field: Field.obs | Field.var, - col: LabelType -): boolean { +export function _isIndex(schema, field, col) { const index = schema.annotations?.[field].index; - return !!(index && index === col); + return index && index === col; } -export function _getColumnDimensionNames( - schema: Schema, - field: Field, - col: LabelType -): LabelArray | undefined { +export function _getColumnDimensionNames(schema, field, col) { /* 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 @@ -58,33 +38,30 @@ export function _getColumnDimensionNames( if (!colSchema) { return undefined; } - if ("dims" in colSchema) { - return colSchema.dims; - } - return [col]; + return colSchema.dims || [col]; } -export function _schemaColumns(schema: Schema, field: Field): string[] { +export function _schemaColumns(schema, field) { switch (field) { - case Field.obs: + case "obs": return Object.keys(schema.annotations.obsByName); - case Field.var: + case "var": return Object.keys(schema.annotations.varByName); - case Field.emb: + case "emb": return Object.keys(schema.layout.obsByName); default: throw new Error(`unknown field name: ${field}`); } } -export function _getWritableColumns(schema: Schema, field: Field): string[] { - if (field !== Field.obs) return []; +export function _getWritableColumns(schema, field) { + if (field !== "obs") return []; return schema.annotations.obs.columns - .filter((v: AnnotationColumnSchema) => v.writable) - .map((v: AnnotationColumnSchema) => v.name); + .filter((v) => v.writable) + .map((v) => v.name); } -export function _isContinuousType(schema: ArraySchema): boolean { +export function _isContinuousType(schema) { const { type } = schema; return !(type === "string" || type === "boolean" || type === "categorical"); } diff --git a/client/src/annoMatrix/viewCreators.ts b/client/src/annoMatrix/viewCreators.js similarity index 66% rename from client/src/annoMatrix/viewCreators.ts rename to client/src/annoMatrix/viewCreators.js index 4cd4d02d..28991b44 100644 --- a/client/src/annoMatrix/viewCreators.ts +++ b/client/src/annoMatrix/viewCreators.js @@ -4,18 +4,8 @@ instances of AnnoMatrix, implementing common UI functions. */ import { AnnoMatrixRowSubsetView, AnnoMatrixClipView } from "./views"; -import AnnoMatrix from "./annoMatrix"; -import { - DenseInt32Index, - IdentityInt32Index, - KeyIndex, -} from "../util/dataframe"; -import { OffsetArray } from "../util/dataframe/types"; -export function isubsetMask( - annoMatrix: AnnoMatrix, - obsMask: Uint8Array -): AnnoMatrixRowSubsetView { +export function isubsetMask(annoMatrix, obsMask) { /* Subset annomatrix to contain the rows which have truish value in the mask. Maks length must equal annoMatrix.nObs (row count). @@ -23,10 +13,7 @@ export function isubsetMask( return isubset(annoMatrix, _maskToList(obsMask)); } -export function isubset( - annoMatrix: AnnoMatrix, - obsOffsets: OffsetArray -): AnnoMatrixRowSubsetView { +export function isubset(annoMatrix, obsOffsets) { /* Subset annomatrix to contain the positions contained in the obsOffsets array @@ -38,10 +25,7 @@ export function isubset( return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); } -export function subset( - annoMatrix: AnnoMatrix, - obsLabels: Int32Array -): AnnoMatrixRowSubsetView { +export function subset(annoMatrix, obsLabels) { /* subset based on labels */ @@ -49,21 +33,14 @@ export function subset( return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); } -export function subsetByIndex( - annoMatrix: AnnoMatrix, - obsIndex: DenseInt32Index | IdentityInt32Index | KeyIndex -): AnnoMatrixRowSubsetView { +export function subsetByIndex(annoMatrix, obsIndex) { /* subset based upon the new obs index. */ return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); } -export function clip( - annoMatrix: AnnoMatrix, - qmin: number, - qmax: number -): AnnoMatrix { +export function clip(annoMatrix, qmin, qmax) { /* Create a view that clips all continuous data to the [min, max] range. The matrix shape does not change, but the continuous values outside the @@ -76,8 +53,11 @@ export function clip( Private utility functions below */ -function _maskToList(mask: Uint8Array): OffsetArray { +function _maskToList(mask) { /* convert masks to lists - method wastes space, but is fast */ + if (!mask) { + return null; + } const list = new Int32Array(mask.length); let elems = 0; for (let i = 0, l = mask.length; i < l; i += 1) { diff --git a/client/src/annoMatrix/views.ts b/client/src/annoMatrix/views.js similarity index 53% rename from client/src/annoMatrix/views.ts rename to client/src/annoMatrix/views.js index 7ddfb6db..5b9b9c26 100644 --- a/client/src/annoMatrix/views.ts +++ b/client/src/annoMatrix/views.js @@ -5,51 +5,25 @@ Views on the annomatrix. all API here is defined in viewCreators.js and annoMat */ import clip from "../util/clip"; import AnnoMatrix from "./annoMatrix"; -import { _whereCacheCreate, WhereCache } from "./whereCache"; +import { _whereCacheCreate } from "./whereCache"; import { _isContinuousType, _getColumnSchema } from "./schema"; -import { - Dataframe, - DataframeValue, - DataframeValueArray, - LabelType, -} from "../util/dataframe"; -import { Query } from "./query"; -import { - AnnotationColumnSchema, - ArraySchema, - Field, - EmbeddingSchema, -} from "../common/types/schema"; -import { LabelIndexBase } from "../util/dataframe/labelIndex"; -type MapFn = ( - field: Field, - colLabel: LabelType, - colSchema: ArraySchema, - colData: DataframeValueArray, - df: Dataframe -) => DataframeValueArray; - -abstract class AnnoMatrixView extends AnnoMatrix { - constructor(viewOf: AnnoMatrix, rowIndex: LabelIndexBase | null = null) { +class AnnoMatrixView extends AnnoMatrix { + constructor(viewOf, rowIndex = null) { const nObs = rowIndex ? rowIndex.size() : viewOf.nObs; super(viewOf.schema, nObs, viewOf.nVar, rowIndex || viewOf.rowIndex); this.viewOf = viewOf; this.isView = true; } - addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix { + addObsAnnoCategory(col, category) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = this.viewOf.addObsAnnoCategory(col, category); newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; return newAnnoMatrix; } - async removeObsAnnoCategory( - col: LabelType, - category: string, - unassignedCategory: string - ): Promise { + async removeObsAnnoCategory(col, category, unassignedCategory) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = await this.viewOf.removeObsAnnoCategory( col, @@ -60,7 +34,7 @@ abstract class AnnoMatrixView extends AnnoMatrix { return newAnnoMatrix; } - dropObsColumn(col: LabelType): AnnoMatrix { + dropObsColumn(col) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = this.viewOf.dropObsColumn(col); newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col); @@ -68,29 +42,21 @@ abstract class AnnoMatrixView extends AnnoMatrix { return newAnnoMatrix; } - addObsColumn( - colSchema: AnnotationColumnSchema, - Ctor: new (n: number) => T, - value: T - ): AnnoMatrix { + addObsColumn(colSchema, Ctor, value) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = this.viewOf.addObsColumn(colSchema, Ctor, value); newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; return newAnnoMatrix; } - renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix { + renameObsColumn(oldCol, newCol) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = this.viewOf.renameObsColumn(oldCol, newCol); newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; return newAnnoMatrix; } - async setObsColumnValues( - col: LabelType, - rowLabels: Int32Array, - value: DataframeValue - ): Promise { + async setObsColumnValues(col, rowLabels, value) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = await this.viewOf.setObsColumnValues( col, @@ -102,11 +68,7 @@ abstract class AnnoMatrixView extends AnnoMatrix { return newAnnoMatrix; } - async resetObsColumnValues( - col: LabelType, - oldValue: T, - newValue: T - ): Promise { + async resetObsColumnValues(col, oldValue, newValue) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = await this.viewOf.resetObsColumnValues( col, @@ -118,7 +80,7 @@ abstract class AnnoMatrixView extends AnnoMatrix { return newAnnoMatrix; } - addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix { + addEmbedding(colSchema) { const newAnnoMatrix = this._clone(); newAnnoMatrix.viewOf = this.viewOf.addEmbedding(colSchema); newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; @@ -127,32 +89,21 @@ abstract class AnnoMatrixView extends AnnoMatrix { } class AnnoMatrixMapView extends AnnoMatrixView { - mapFn: MapFn; - /* - A view which knows how to transform its data. - */ - constructor(viewOf: AnnoMatrix, mapFn: MapFn) { + A view which knows how to transform its data. + */ + constructor(viewOf, mapFn) { super(viewOf); this.mapFn = mapFn; } - async _doLoad( - field: Field, - query: Query - ): Promise<[WhereCache | null, Dataframe]> { + async _doLoad(field, query) { const df = await this.viewOf._fetch(field, query); - const dfMapped = df.mapColumns( - (colData: DataframeValueArray, colIdx: number) => { - const colLabel = df.colIndex.getLabel(colIdx); - // @ts-expect-error ts-migrate --- TODO revisit: - // `colLabel`: Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'. - const colSchema = _getColumnSchema(this.schema, field, colLabel); - // @ts-expect-error ts-migrate --- TODO revisit: - // `colLabel`: Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'. - return this.mapFn(field, colLabel, colSchema, colData, df); - } - ); + const dfMapped = df.mapColumns((colData, colIdx) => { + const colLabel = df.colIndex.getLabel(colIdx); + const colSchema = _getColumnSchema(this.schema, field, colLabel); + return this.mapFn(field, colLabel, colSchema, colData, df); + }); const whereCacheUpdate = _whereCacheCreate( field, query, @@ -163,23 +114,12 @@ class AnnoMatrixMapView extends AnnoMatrixView { } export class AnnoMatrixClipView extends AnnoMatrixMapView { - clipRange: [number, number]; - - isClipped: boolean; - /* - A view which is a clipped transformation of its parent - */ - constructor(viewOf: AnnoMatrix, qmin: number, qmax: number) { - super( - viewOf, - ( - field: Field, - colLabel: LabelType, - colSchema: ArraySchema, - colData: DataframeValueArray, - df: Dataframe - ) => _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) + A view which is a clipped transformation of its parent + */ + constructor(viewOf, qmin, qmax) { + super(viewOf, (field, colLabel, colSchema, colData, df) => + _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) ); this.isClipped = true; this.clipRange = [qmin, qmax]; @@ -189,21 +129,18 @@ export class AnnoMatrixClipView extends AnnoMatrixMapView { export class AnnoMatrixRowSubsetView extends AnnoMatrixView { /* - A view which is a subset of total rows. - */ - constructor(viewOf: AnnoMatrix, rowIndex: LabelIndexBase) { + A view which is a subset of total rows. + */ + constructor(viewOf, rowIndex) { super(viewOf, rowIndex); Object.seal(this); } - async _doLoad( - field: Field, - query: Query - ): Promise<[WhereCache | null, Dataframe]> { + async _doLoad(field, query) { const df = await this.viewOf._fetch(field, query); // don't try to row-subset the var dimension. - if (field === Field.var) { + if (field === "var") { return [null, df]; } @@ -221,23 +158,15 @@ export class AnnoMatrixRowSubsetView extends AnnoMatrixView { Utility functions below */ -function _clipAnnoMatrix( - field: Field, - colLabel: LabelType, - colSchema: ArraySchema, - colData: DataframeValueArray, - df: Dataframe, - qmin: number, - qmax: number -): DataframeValueArray { +function _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) { /* only clip obs and var scalar columns */ - if (field !== Field.obs && field !== Field.X) return colData; + if (field !== "obs" && field !== "X") return colData; if (!_isContinuousType(colSchema)) return colData; if (qmin < 0) qmin = 0; if (qmax > 1) qmax = 1; if (qmin === 0 && qmax === 1) return colData; - const quantiles = df.col(colLabel).summarizeContinuous().percentiles; + const quantiles = df.col(colLabel).summarize().percentiles; const lower = quantiles[100 * qmin]; const upper = quantiles[100 * qmax]; const clippedData = clip(colData.slice(), lower, upper, Number.NaN); diff --git a/client/src/annoMatrix/whereCache.ts b/client/src/annoMatrix/whereCache.js similarity index 77% rename from client/src/annoMatrix/whereCache.ts rename to client/src/annoMatrix/whereCache.js index 440565c4..e67c5d49 100644 --- a/client/src/annoMatrix/whereCache.ts +++ b/client/src/annoMatrix/whereCache.js @@ -2,7 +2,7 @@ Private support functions. This implements a query resolver cache, mapping a query onto the column labels -resolved by that query. These labels are then used to manage the actual data cache, +resolved by that query. These labels are then used to manage the acutal data cache, which stores data by the resolved label. There are three query forms: @@ -49,33 +49,9 @@ creates a cache entry of: } */ import { _getColumnDimensionNames } from "./schema"; -import { _hashStringValues, Query } from "./query"; -import { Field, Schema } from "../common/types/schema"; -import { LabelArray } from "../util/dataframe/types"; +import { _hashStringValues } from "./query"; -export interface WhereCache { - summarize?: { - [key: string]: { - [key: string]: WhereCacheTerms; - }; - }; - where?: { - [key: string]: WhereCacheTerms; - }; -} - -export type WhereCacheColumnLabels = LabelArray; - -interface WhereCacheTerms { - [key: string]: Map>; -} - -export function _whereCacheGet( - whereCache: WhereCache, - schema: Schema, - field: Field, - query: Query -): WhereCacheColumnLabels | [undefined] { +export function _whereCacheGet(whereCache, schema, field, query) { /* query will either be an where query (object) or a column name (string). @@ -83,7 +59,7 @@ export function _whereCacheGet( */ if (typeof query === "object") { - if ("where" in query) { + if (query.where) { const { field: queryField, column: queryColumn, @@ -92,7 +68,7 @@ export function _whereCacheGet( const columnMap = whereCache?.where?.[field]?.[queryField]; return columnMap?.get(queryColumn)?.get(queryValue) ?? [undefined]; } - if ("summarize" in query) { + if (query.summarize) { const { method, field: queryField, @@ -109,17 +85,13 @@ export function _whereCacheGet( return _getColumnDimensionNames(schema, field, query) ?? [undefined]; } -export function _whereCacheCreate( - field: Field, - query: Query, - columnLabels: LabelArray -): WhereCache | null { +export function _whereCacheCreate(field, query, columnLabels) { /* Create a new whereCache */ if (typeof query !== "object") return null; - if ("where" in query) { + if (query.where) { const { field: queryField, column: queryColumn, @@ -135,7 +107,7 @@ export function _whereCacheCreate( }, }; } - if ("summarize" in query) { + if (query.summarize) { const { method, field: queryField, @@ -159,25 +131,20 @@ export function _whereCacheCreate( return {}; } -function __mergeQueries(dst: WhereCacheTerms, src: WhereCacheTerms) { +function __mergeQueries(dst, src) { for (const [queryField, columnMap] of Object.entries(src)) { dst[queryField] = dst[queryField] || new Map(); for (const [queryColumn, valueMap] of columnMap) { if (!dst[queryField].has(queryColumn)) dst[queryField].set(queryColumn, new Map()); for (const [queryValue, columnLabels] of valueMap) { - // @ts-expect-error ts-migrate --- TODO revisit: - // `dst[queryField].get(queryColumn)` Object is possibly 'undefined'. dst[queryField].get(queryColumn).set(queryValue, columnLabels); } } } } -function __whereCacheMerge( - dst: WhereCache, - src: WhereCache | null -): WhereCache { +function __whereCacheMerge(dst, src) { /* merge src into dst (modifies dst) */ @@ -204,6 +171,6 @@ function __whereCacheMerge( return dst; } -export function _whereCacheMerge(...caches: (WhereCache | null)[]): WhereCache { - return caches.reduce(__whereCacheMerge, {} as WhereCache); +export function _whereCacheMerge(...caches) { + return caches.reduce(__whereCacheMerge, {}); } diff --git a/client/src/common/types/arraytypes.ts b/client/src/common/types/arraytypes.ts deleted file mode 100644 index 266b5be2..00000000 --- a/client/src/common/types/arraytypes.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Utility type and interface definitions. - */ - -/** - * TypedArrays that can be assigned to a number. - */ -export type TypedArray = - | Int8Array - | Uint8Array - | Uint8ClampedArray - | Int16Array - | Uint16Array - | Int32Array - | Uint32Array - | Float32Array - | Float64Array; - -export type UnsignedTypedArray = Uint8Array | Uint16Array | Uint32Array; -export type FloatTypedArray = Float32Array | Float64Array; - -export type TypedArrayConstructor = - | Int8ArrayConstructor - | Uint8ArrayConstructor - | Int16ArrayConstructor - | Uint16ArrayConstructor - | Int32ArrayConstructor - | Uint32ArrayConstructor - | Float32ArrayConstructor - | Float64ArrayConstructor; - -export type AnyArray = Array | TypedArray; - -export interface GenericArrayConstructor { - new ( - ...args: ConstructorParameters< - typeof Int8Array & - typeof Uint8Array & - typeof Int16Array & - typeof Uint16Array & - typeof Int32Array & - typeof Uint32Array & - typeof Float32Array & - typeof Float64Array & - typeof Array - > - ): T; -} - -export type NumberArray = Array | TypedArray; - -export type Int8 = Int8Array[0]; -export type Uint8 = Uint8Array[0]; -export type Int16 = Int16Array[0]; -export type Uint16 = Uint16Array[0]; -export type Int32 = Int32Array[0]; -export type Uint32 = Uint32Array[0]; -export type Float32 = Float32Array[0]; -export type Float64 = Float64Array[0]; - -/** - * Test if the parameter is a TypedArray. - * @param tbd - value to be tested - * @returns true if `tbd` is a TypedArray, false if not. - */ -export function isTypedArray(tbd: unknown): tbd is TypedArray { - return ( - ArrayBuffer.isView(tbd) && - Object.prototype.toString.call(tbd) !== "[object DataView]" - ); -} - -/** - * Test if the paramter is a float TypedArray - * @param tbd - value to be tested - * @returns - true if `tbd` is a float typed array. - */ -export function isFloatTypedArray(tbd: unknown): tbd is FloatTypedArray { - return tbd instanceof Float32Array || tbd instanceof Float64Array; -} - -/** - * Test if the paramter is a float TypedArray - * @param tbd - value to be tested - * @returns - true if `tbd` is a float typed array. - */ -export function isUnsignedTypedArray(tbd: unknown): tbd is UnsignedTypedArray { - return ( - tbd instanceof Uint8Array || - tbd instanceof Uint16Array || - tbd instanceof Uint32Array - ); -} - -/** - * Test if the parameter is a TypedArray or Array - * @param tbd - value to be tested - * @returns - true if `tbd` is a TypedArray or Array - */ -export function isAnyArray(tbd: unknown): tbd is AnyArray { - return Array.isArray(tbd) || isTypedArray(tbd); -} diff --git a/client/src/common/types/entities.ts b/client/src/common/types/entities.ts deleted file mode 100644 index 49b6362c..00000000 --- a/client/src/common/types/entities.ts +++ /dev/null @@ -1,8 +0,0 @@ -// If a globally shared type or interface doesn't have a clear owner, put it here - -/** - * Flags informing garbage collection-related logic. - */ -export interface GCHints { - isHot: boolean; -} diff --git a/client/src/common/types/schema.ts b/client/src/common/types/schema.ts deleted file mode 100644 index 3ce10637..00000000 --- a/client/src/common/types/schema.ts +++ /dev/null @@ -1,76 +0,0 @@ -export type Category = number | string | boolean; - -export interface AnnotationColumnSchema { - categories?: Category[]; - name: string; - type: "string" | "float32" | "int32" | "categorical" | "boolean"; - writable: boolean; -} - -export interface XMatrixSchema { - nObs: number; - nVar: number; - // TODO(thuang): Not sure what other types are available - type: "float32"; -} - -export interface EmbeddingSchema { - dims: string[]; - name: string; - // TODO(thuang): Not sure what other types are available - type: "float32"; -} -interface RawLayoutSchema { - obs: EmbeddingSchema[]; - var?: EmbeddingSchema[]; -} - -interface RawAnnotationsSchema { - obs: { - columns: AnnotationColumnSchema[]; - index: string; - }; - var: { - columns: AnnotationColumnSchema[]; - index: string; - }; -} - -export interface RawSchema { - annotations: RawAnnotationsSchema; - dataframe: XMatrixSchema; - layout: RawLayoutSchema; -} - -interface AnnotationsSchema extends RawAnnotationsSchema { - obsByName: { [name: string]: AnnotationColumnSchema }; - varByName: { [name: string]: AnnotationColumnSchema }; -} - -interface LayoutSchema extends RawLayoutSchema { - obsByName: { [name: string]: EmbeddingSchema }; - varByName: { [name: string]: EmbeddingSchema }; -} - -export interface Schema extends RawSchema { - annotations: AnnotationsSchema; - layout: LayoutSchema; -} - -/** - * Sub-schema objects describing the schema for a primitive Array or Matrix in one of the fields. - */ -export type ArraySchema = - | AnnotationColumnSchema - | EmbeddingSchema - | XMatrixSchema; - -/** - * Set of data / metadata objects that must be specified in a CXG. - */ -export enum Field { - "obs" = "obs", - "var" = "var", - "emb" = "emb", - "X" = "X", -} diff --git a/client/src/components/annoDialog.js b/client/src/components/annoDialog.js new file mode 100644 index 00000000..8064b146 --- /dev/null +++ b/client/src/components/annoDialog.js @@ -0,0 +1,94 @@ +import React from "react"; +import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core"; + +class AnnoDialog extends React.PureComponent { + constructor(props) { + super(props); + this.state = {}; + } + + render() { + const { + isActive, + text, + title, + instruction, + cancelTooltipContent, + errorMessage, + validationError, + annoSelect, + annoInput, + secondaryInstructions, + secondaryInput, + handleCancel, + handleSubmit, + primaryButtonText, + secondaryButtonText, + handleSecondaryButtonSubmit, + primaryButtonProps, + } = this.props; + + return ( + +
{ + e.preventDefault(); + }} + > +
+
+

{instruction}

+ {annoInput || null} +

+ {errorMessage} +

+ {/* we might rename, secondary button and secondary input are not related */} + {secondaryInstructions && ( +

+ {secondaryInstructions} +

+ )} + {secondaryInput || null} +
+ {annoSelect || null} +
+
+
+ + + + {/* we might rename, secondary button and secondary input are not related */} + {handleSecondaryButtonSubmit && secondaryButtonText ? ( + + ) : null} + +
+
+
+
+ ); + } +} + +export default AnnoDialog; diff --git a/client/src/components/annoDialog.tsx b/client/src/components/annoDialog.tsx deleted file mode 100644 index 04042378..00000000 --- a/client/src/components/annoDialog.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React from "react"; -import { Button, Tooltip, Dialog, Classes, Colors } from "@blueprintjs/core"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class AnnoDialog extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = {}; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isActive' does not exist on type 'Readon... Remove this comment to see the full error message - isActive, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'text' does not exist on type 'Readonly<{... Remove this comment to see the full error message - text, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'title' does not exist on type 'Readonly<... Remove this comment to see the full error message - title, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'instruction' does not exist on type 'Rea... Remove this comment to see the full error message - instruction, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'cancelTooltipContent' does not exist on ... Remove this comment to see the full error message - cancelTooltipContent, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'errorMessage' does not exist on type 'Re... Remove this comment to see the full error message - errorMessage, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'validationError' does not exist on type ... Remove this comment to see the full error message - validationError, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoSelect' does not exist on type 'Read... Remove this comment to see the full error message - annoSelect, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoInput' does not exist on type 'Reado... Remove this comment to see the full error message - annoInput, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryInstructions' does not exist on... Remove this comment to see the full error message - secondaryInstructions, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryInput' does not exist on type '... Remove this comment to see the full error message - secondaryInput, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCancel' does not exist on type 'Re... Remove this comment to see the full error message - handleCancel, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubmit' does not exist on type 'Re... Remove this comment to see the full error message - handleSubmit, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'primaryButtonText' does not exist on typ... Remove this comment to see the full error message - primaryButtonText, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'secondaryButtonText' does not exist on t... Remove this comment to see the full error message - secondaryButtonText, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSecondaryButtonSubmit' does not ex... Remove this comment to see the full error message - handleSecondaryButtonSubmit, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'primaryButtonProps' does not exist on ty... Remove this comment to see the full error message - primaryButtonProps, - } = this.props; - - return ( - -
{ - e.preventDefault(); - }} - > -
-
-

{instruction}

- {annoInput || null} -

- {errorMessage} -

- {/* we might rename, secondary button and secondary input are not related */} - {secondaryInstructions && ( -

- {secondaryInstructions} -

- )} - {secondaryInput || null} -
- {annoSelect || null} -
-
-
- - - - {/* we might rename, secondary button and secondary input are not related */} - {handleSecondaryButtonSubmit && secondaryButtonText ? ( - - ) : null} - -
-
-
-
- ); - } -} - -export default AnnoDialog; diff --git a/client/src/components/app.tsx b/client/src/components/app.js similarity index 53% rename from client/src/components/app.tsx rename to client/src/components/app.js index cf585686..eb46d3a6 100644 --- a/client/src/components/app.tsx +++ b/client/src/components/app.js @@ -15,38 +15,30 @@ import TermsOfServicePrompt from "./termsPrompt"; import actions from "../actions"; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - loading: (state as any).controls.loading, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - error: (state as any).controls.error, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - graphRenderCounter: (state as any).controls.graphRenderCounter, + loading: state.controls.loading, + error: state.controls.error, + graphRenderCounter: state.controls.graphRenderCounter, })) class App extends React.Component { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch } = this.props; + /* listen for url changes, fire one when we start the app up */ window.addEventListener("popstate", this._onURLChanged); this._onURLChanged(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. + dispatch(actions.doInitialDataLoad(window.location.search)); this.forceUpdate(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _onURLChanged() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch } = this.props; + dispatch({ type: "url changed", url: document.location.href }); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'loading' does not exist on type 'Readonl... Remove this comment to see the full error message const { loading, error, graphRenderCounter } = this.props; return ( @@ -78,16 +70,13 @@ class App extends React.Component { {loading || error ? null : ( - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {(viewportRef: any) => ( + {(viewportRef) => ( <> - {/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */} - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ key: any; viewportRef: any; }' is not assi... Remove this comment to see the full error message */} )} diff --git a/client/src/components/autosave/filenameDialog.tsx b/client/src/components/autosave/filenameDialog.js similarity index 50% rename from client/src/components/autosave/filenameDialog.tsx rename to client/src/components/autosave/filenameDialog.js index 823a4286..83f91eb0 100644 --- a/client/src/components/autosave/filenameDialog.tsx +++ b/client/src/components/autosave/filenameDialog.js @@ -11,78 +11,60 @@ import { Tooltip, } from "@blueprintjs/core"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - idhash: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.["annotations-user-data-idhash"] ?? null, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - auth: (state as any).config?.authentication, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userInfo: (state as any).userInfo, - writableCategoriesEnabled: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.annotations ?? false, + idhash: state.config?.parameters?.["annotations-user-data-idhash"] ?? null, + annotations: state.annotations, + auth: state.config?.authentication, + userInfo: state.userInfo, + writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, writableGenesetsEnabled: !( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - ((state as any).config?.parameters?.annotations_genesets_readonly ?? true) + state.config?.parameters?.annotations_genesets_readonly ?? true ), })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class FilenameDialog extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class FilenameDialog extends React.Component { + constructor(props) { super(props); this.state = { filenameText: "", }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. dismissFilenameDialog = () => {}; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleCreateFilename = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch } = this.props; const { filenameText } = this.state; + dispatch({ type: "set annotations collection name", data: filenameText, }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. filenameError = () => { const legalNames = /^\w+$/; const { filenameText } = this.state; let err = false; + if (filenameText === "") { - // @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'boolean'. err = "empty_string"; } else if (!legalNames.test(filenameText)) { /* - IMPORTANT: this test must ultimately match the test applied by the - backend, which is designed to ensure a safe file name can be created - from the data collection name. If you change this, you will also need - to change the validation code in the backend, or it will have no effect. - */ - // @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'boolean'. + IMPORTANT: this test must ultimately match the test applied by the + backend, which is designed to ensure a safe file name can be created + from the data collection name. If you change this, you will also need + to change the validation code in the backend, or it will have no effect. + */ err = "characters"; } + return err; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. filenameErrorMessage = () => { const err = this.filenameError(); let markup = null; - // @ts-expect-error ts-migrate(2367) FIXME: This condition will always return 'false' since th... Remove this comment to see the full error message + if (err === "empty_string") { markup = ( { Name cannot be blank ); - // @ts-expect-error ts-migrate(2367) FIXME: This condition will always return 'false' since th... Remove this comment to see the full error message } else if (err === "characters") { markup = ( { return markup; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message writableCategoriesEnabled, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'writableGenesetsEnabled' does not exist ... Remove this comment to see the full error message writableGenesetsEnabled, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message annotations, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'idhash' does not exist on type 'Readonly... Remove this comment to see the full error message idhash, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'userInfo' does not exist on type 'Readon... Remove this comment to see the full error message userInfo, } = this.props; const { filenameText } = this.state; + return (writableCategoriesEnabled || writableGenesetsEnabled) && annotations.promptForFilename && !annotations.dataCollectionNameIsReadOnly && @@ -152,7 +128,6 @@ class FilenameDialog extends React.Component<{}, State> { this.setState({ filenameText: e.target.value }) @@ -163,14 +138,12 @@ class FilenameDialog extends React.Component<{}, State> {

- {/* @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. */} {this.filenameErrorMessage(filenameText)}

@@ -198,7 +171,6 @@ class FilenameDialog extends React.Component<{}, State> {
+
+
+ ) +; + +export default StillLoading; diff --git a/client/src/components/brushableHistogram/loading.tsx b/client/src/components/brushableHistogram/loading.tsx deleted file mode 100644 index 65b73e16..00000000 --- a/client/src/components/brushableHistogram/loading.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from "react"; -import { Button } from "@blueprintjs/core"; - -import * as globals from "../../globals"; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const StillLoading = ({ zebra, displayName }: any) => ( - /* - Render a loading indicator for the field. - */ -
-
-
-
- {displayName} -
-
-
-
-
-); -export default StillLoading; diff --git a/client/src/components/categorical/annoSelect.js b/client/src/components/categorical/annoSelect.js new file mode 100644 index 00000000..6d184e0a --- /dev/null +++ b/client/src/components/categorical/annoSelect.js @@ -0,0 +1,54 @@ +import React from "react"; +import { Button, MenuItem } from "@blueprintjs/core"; +import { Select } from "@blueprintjs/select"; + +class DuplicateCategorySelect extends React.PureComponent { + constructor(props) { + super(props); + this.state = {}; + } + + render() { + const { + allCategoryNames, + categoryToDuplicate, + handleModalDuplicateCategorySelection, + } = this.props; + return ( +
+

+ Optionally duplicate all labels & cell assignments from existing + category into new category: +

+ +
+ ); + } +} + +export default DuplicateCategorySelect; diff --git a/client/src/components/categorical/annoSelect.tsx b/client/src/components/categorical/annoSelect.tsx deleted file mode 100644 index a803156b..00000000 --- a/client/src/components/categorical/annoSelect.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from "react"; -import { Button, MenuItem } from "@blueprintjs/core"; -import { Select } from "@blueprintjs/select"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class DuplicateCategorySelect extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = {}; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'allCategoryNames' does not exist on type... Remove this comment to see the full error message - allCategoryNames, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryToDuplicate' does not exist on t... Remove this comment to see the full error message - categoryToDuplicate, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleModalDuplicateCategorySelection' d... Remove this comment to see the full error message - handleModalDuplicateCategorySelection, - } = this.props; - return ( -
-

- Optionally duplicate all labels & cell assignments from existing - category into new category: -

- -
- ); - } -} - -export default DuplicateCategorySelect; diff --git a/client/src/components/categorical/category/annoDialogAddLabel.js b/client/src/components/categorical/category/annoDialogAddLabel.js new file mode 100644 index 00000000..729b2034 --- /dev/null +++ b/client/src/components/categorical/category/annoDialogAddLabel.js @@ -0,0 +1,113 @@ +import React from "react"; +import { connect } from "react-redux"; +import AnnoDialog from "../../annoDialog"; +import LabelInput from "../../labelInput"; +import { labelPrompt, isLabelErroneous } from "../labelUtil"; +import actions from "../../../actions"; + +@connect((state) => ({ + annotations: state.annotations, + schema: state.annoMatrix?.schema, + obsCrossfilter: state.obsCrossfilter, +})) +class Category extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + newLabelText: "", + }; + } + + disableAddNewLabelMode = (e) => { + const { dispatch } = this.props; + this.setState({ + newLabelText: "", + }); + dispatch({ + type: "annotation: disable add new label mode", + }); + if (e) e.preventDefault(); + }; + + handleAddNewLabelToCategory = (e) => { + const { dispatch, metadataField } = this.props; + const { newLabelText } = this.state; + + this.disableAddNewLabelMode(); + dispatch( + actions.annotationCreateLabelInCategory( + metadataField, + newLabelText, + false + ) + ); + e.preventDefault(); + }; + + addLabelAndAssignCells = (e) => { + const { dispatch, metadataField } = this.props; + const { newLabelText } = this.state; + + this.disableAddNewLabelMode(); + dispatch( + actions.annotationCreateLabelInCategory(metadataField, newLabelText, true) + ); + e.preventDefault(); + }; + + labelNameError = (name) => { + const { metadataField, schema } = this.props; + return isLabelErroneous(name, metadataField, schema); + }; + + instruction = (label) => labelPrompt(this.labelNameError(label), "New, unique label", ":"); + + handleChangeOrSelect = (label) => { + this.setState({ newLabelText: label }); + }; + + render() { + const { newLabelText } = this.state; + const { metadataField, annotations, obsCrossfilter } = this.props; + + return ( + <> + + } + /> + + ); + } +} + +export default Category; diff --git a/client/src/components/categorical/category/annoDialogAddLabel.tsx b/client/src/components/categorical/category/annoDialogAddLabel.tsx deleted file mode 100644 index 29235feb..00000000 --- a/client/src/components/categorical/category/annoDialogAddLabel.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import AnnoDialog from "../../annoDialog"; -import LabelInput from "../../labelInput"; -import { labelPrompt, isLabelErroneous } from "../labelUtil"; -import actions from "../../../actions"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - obsCrossfilter: (state as any).obsCrossfilter, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Category extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = { - newLabelText: "", - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - disableAddNewLabelMode = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - this.setState({ - newLabelText: "", - }); - dispatch({ - type: "annotation: disable add new label mode", - }); - if (e) e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleAddNewLabelToCategory = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - const { newLabelText } = this.state; - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. - this.disableAddNewLabelMode(); - dispatch( - actions.annotationCreateLabelInCategory( - metadataField, - newLabelText, - false - ) - ); - e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - addLabelAndAssignCells = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - const { newLabelText } = this.state; - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. - this.disableAddNewLabelMode(); - dispatch( - actions.annotationCreateLabelInCategory(metadataField, newLabelText, true) - ); - e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labelNameError = (name: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - const { metadataField, schema } = this.props; - return isLabelErroneous(name, metadataField, schema); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - instruction = (label: any) => - labelPrompt(this.labelNameError(label), "New, unique label", ":"); - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChangeOrSelect = (label: any) => { - this.setState({ newLabelText: label }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { newLabelText } = this.state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - const { metadataField, annotations, obsCrossfilter } = this.props; - return ( - <> - - } - /> - - ); - } -} - -export default Category; diff --git a/client/src/components/categorical/category/annoDialogEditCategoryName.js b/client/src/components/categorical/category/annoDialogEditCategoryName.js new file mode 100644 index 00000000..f4d96b2c --- /dev/null +++ b/client/src/components/categorical/category/annoDialogEditCategoryName.js @@ -0,0 +1,149 @@ +import React from "react"; +import { connect } from "react-redux"; +import AnnoDialog from "../../annoDialog"; +import LabelInput from "../../labelInput"; +import { labelPrompt } from "../labelUtil"; + +import { AnnotationsHelpers } from "../../../util/stateManager"; +import actions from "../../../actions"; + +@connect((state) => ({ + annotations: state.annotations, + schema: state.annoMatrix?.schema, +})) +class AnnoDialogEditCategoryName extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + newCategoryText: props.metadataField, + }; + } + + handleChangeOrSelect = (name) => { + this.setState({ + newCategoryText: name, + }); + }; + + disableEditCategoryMode = () => { + const { dispatch, metadataField } = this.props; + dispatch({ + type: "annotation: disable category edit mode", + }); + this.setState({ newCategoryText: metadataField }); + }; + + handleEditCategory = (e) => { + const { dispatch, metadataField } = this.props; + const { newCategoryText } = this.state; + + /* + test for uniqueness against *all* annotation names, not just the subset + we render as categorical. + */ + const { schema } = this.props; + const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); + + if ( + (allCategoryNames.indexOf(newCategoryText) > -1 && + newCategoryText !== metadataField) || + newCategoryText === "" + ) { + return; + } + + this.disableEditCategoryMode(); + + if (metadataField !== newCategoryText) + dispatch( + actions.annotationRenameCategoryAction(metadataField, newCategoryText) + ); + e.preventDefault(); + }; + + editedCategoryNameError = (name) => { + const { metadataField } = this.props; + + /* check for syntax errors in category name */ + const error = AnnotationsHelpers.annotationNameIsErroneous(name); + if (error) { + return error; + } + + /* check for duplicative categories */ + + /* + test for uniqueness against *all* annotation names, not just the subset + we render as categorical. + */ + const { schema } = this.props; + const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); + + const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1; + const sameName = name === metadataField; + if (categoryNameAlreadyExists && !sameName) { + return "duplicate"; + } + + /* otherwise, no error */ + return false; + }; + + instruction = (name) => labelPrompt( + this.editedCategoryNameError(name), + "New, unique category name", + ":" + ); + + allCategoryNames() { + const { schema } = this.props; + return schema.annotations.obs.columns.map((c) => c.name); + } + + render() { + const { newCategoryText } = this.state; + const { metadataField, annotations } = this.props; + + return ( + <> + + } + /> + + ); + } +} + +export default AnnoDialogEditCategoryName; diff --git a/client/src/components/categorical/category/annoDialogEditCategoryName.tsx b/client/src/components/categorical/category/annoDialogEditCategoryName.tsx deleted file mode 100644 index 8ae27444..00000000 --- a/client/src/components/categorical/category/annoDialogEditCategoryName.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import AnnoDialog from "../../annoDialog"; -import LabelInput from "../../labelInput"; -import { labelPrompt } from "../labelUtil"; - -import { AnnotationsHelpers } from "../../../util/stateManager"; -import actions from "../../../actions"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class AnnoDialogEditCategoryName extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message - newCategoryText: props.metadataField, - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChangeOrSelect = (name: any) => { - this.setState({ - newCategoryText: name, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - disableEditCategoryMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - dispatch({ - type: "annotation: disable category edit mode", - }); - this.setState({ newCategoryText: metadataField }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleEditCategory = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - const { newCategoryText } = this.state; - /* - test for uniqueness against *all* annotation names, not just the subset - we render as categorical. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - const { schema } = this.props; - const allCategoryNames = schema.annotations.obs.columns.map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (c: any) => c.name - ); - if ( - (allCategoryNames.indexOf(newCategoryText) > -1 && - newCategoryText !== metadataField) || - newCategoryText === "" - ) { - return; - } - this.disableEditCategoryMode(); - if (metadataField !== newCategoryText) - dispatch( - actions.annotationRenameCategoryAction(metadataField, newCategoryText) - ); - e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - editedCategoryNameError = (name: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - const { metadataField } = this.props; - /* check for syntax errors in category name */ - const error = AnnotationsHelpers.annotationNameIsErroneous(name); - if (error) { - return error; - } - /* check for duplicative categories */ - /* - test for uniqueness against *all* annotation names, not just the subset - we render as categorical. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - const { schema } = this.props; - const allCategoryNames = schema.annotations.obs.columns.map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (c: any) => c.name - ); - const categoryNameAlreadyExists = allCategoryNames.indexOf(name) > -1; - const sameName = name === metadataField; - if (categoryNameAlreadyExists && !sameName) { - return "duplicate"; - } - /* otherwise, no error */ - return false; - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - instruction = (name: any) => - labelPrompt( - this.editedCategoryNameError(name), - "New, unique category name", - ":" - ); - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - allCategoryNames() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - const { schema } = this.props; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - return schema.annotations.obs.columns.map((c: any) => c.name); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { newCategoryText } = this.state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - const { metadataField, annotations } = this.props; - return ( - <> - - } - /> - - ); - } -} - -export default AnnoDialogEditCategoryName; diff --git a/client/src/components/categorical/category/annoMenuCategory.tsx b/client/src/components/categorical/category/annoMenuCategory.js similarity index 54% rename from client/src/components/categorical/category/annoMenuCategory.tsx rename to client/src/components/categorical/category/annoMenuCategory.js index d8c132c4..706ff63a 100644 --- a/client/src/components/categorical/category/annoMenuCategory.tsx +++ b/client/src/components/categorical/category/annoMenuCategory.js @@ -16,25 +16,16 @@ import { IconNames } from "@blueprintjs/icons"; import * as globals from "../../../globals"; import actions from "../../../actions"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, + annotations: state.annotations, })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class AnnoMenuCategory extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class AnnoMenuCategory extends React.PureComponent { + constructor(props) { super(props); this.state = {}; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. activateAddNewLabelMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField } = this.props; dispatch({ type: "annotation: activate add new label mode", @@ -42,39 +33,30 @@ class AnnoMenuCategory extends React.PureComponent<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. activateEditCategoryMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField } = this.props; + dispatch({ type: "annotation: activate category edit mode", data: metadataField, }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDeleteCategory = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField } = this.props; dispatch(actions.annotationDeleteCategoryAction(metadataField)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message annotations, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message isUserAnno, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'createText' does not exist on type 'Read... Remove this comment to see the full error message createText, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'editText' does not exist on type 'Readon... Remove this comment to see the full error message editText, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'deleteText' does not exist on type 'Read... Remove this comment to see the full error message deleteText, } = this.props; + return ( <> {isUserAnno ? ( diff --git a/client/src/components/categorical/category/index.js b/client/src/components/categorical/category/index.js new file mode 100644 index 00000000..5d20b2c7 --- /dev/null +++ b/client/src/components/categorical/category/index.js @@ -0,0 +1,617 @@ +import React, { useRef, useEffect } from "react"; +import { connect, shallowEqual } from "react-redux"; +import { FaChevronRight, FaChevronDown } from "react-icons/fa"; +import { + AnchorButton, + Button, + Classes, + Position, + Tooltip, +} from "@blueprintjs/core"; +import { Flipper, Flipped } from "react-flip-toolkit"; +import Async from "react-async"; +import memoize from "memoize-one"; + +import Value from "../value"; +import AnnoMenu from "./annoMenuCategory"; +import AnnoDialogEditCategoryName from "./annoDialogEditCategoryName"; +import AnnoDialogAddLabel from "./annoDialogAddLabel"; +import Truncate from "../../util/truncate"; +import { CategoryCrossfilterContext } from "../categoryContext"; + +import * as globals from "../../../globals"; +import { createCategorySummaryFromDfCol } from "../../../util/stateManager/controlsHelpers"; +import { + createColorTable, + createColorQuery, +} from "../../../util/stateManager/colorHelpers"; +import actions from "../../../actions"; + +const LABEL_WIDTH = globals.leftSidebarWidth - 100; +const ANNO_BUTTON_WIDTH = 50; +const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH; + +@connect((state, ownProps) => { + const schema = state.annoMatrix?.schema; + const { metadataField } = ownProps; + const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable; + const categoricalSelection = state.categoricalSelection?.[metadataField]; + return { + colors: state.colors, + categoricalSelection, + annotations: state.annotations, + annoMatrix: state.annoMatrix, + schema, + crossfilter: state.obsCrossfilter, + isUserAnno, + genesets: state.genesets.genesets, + }; +}) +class Category extends React.PureComponent { + static getSelectionState( + categoricalSelection, + metadataField, + categorySummary + ) { + // total number of categories in this dimension + const totalCatCount = categorySummary.numCategoryValues; + // number of selected options in this category + const selectedCatCount = categorySummary.categoryValues.reduce( + (res, label) => (categoricalSelection.get(label) ?? true ? res + 1 : res), + 0 + ); + return selectedCatCount === totalCatCount + ? "all" + : selectedCatCount === 0 + ? "none" + : "some"; + } + + static watchAsync(props, prevProps) { + return !shallowEqual(props.watchProps, prevProps.watchProps); + } + + createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol); + + getSelectionState(categorySummary) { + const { categoricalSelection, metadataField } = this.props; + return Category.getSelectionState( + categoricalSelection, + metadataField, + categorySummary + ); + } + + handleColorChange = () => { + const { dispatch, metadataField } = this.props; + dispatch({ + type: "color by categorical metadata", + colorAccessor: metadataField, + }); + }; + + handleCategoryClick = () => { + const { annotations, metadataField, onExpansionChange } = this.props; + const editingCategory = + annotations.isEditingCategoryName && + annotations.categoryBeingEdited === metadataField; + if (!editingCategory) { + onExpansionChange(metadataField); + } + }; + + handleCategoryKeyPress = (e) => { + if (e.key === "Enter") { + this.handleCategoryClick(); + } + }; + + handleToggleAllClick = (categorySummary) => { + const isChecked = this.getSelectionState(categorySummary); + if (isChecked === "all") { + this.toggleNone(categorySummary); + } else { + this.toggleAll(categorySummary); + } + }; + + fetchAsyncProps = async (props) => { + const { annoMatrix, metadataField, colors } = props.watchProps; + const { crossfilter } = this.props; + + const [categoryData, categorySummary, colorData] = await this.fetchData( + annoMatrix, + metadataField, + colors + ); + + return { + categoryData, + categorySummary, + colorData, + crossfilter, + ...this.updateColorTable(colorData), + handleCategoryToggleAllClick: () => + this.handleToggleAllClick(categorySummary), + }; + }; + + async fetchData(annoMatrix, metadataField, colors) { + /* + fetch our data and the color-by data if appropriate, and then build a summary + of our category and a color table for the color-by annotation. + */ + const { schema } = annoMatrix; + const { colorAccessor, colorMode } = colors; + const { genesets } = this.props; + let colorDataPromise = Promise.resolve(null); + if (colorAccessor) { + const query = createColorQuery( + colorMode, + colorAccessor, + schema, + genesets + ); + if (query) colorDataPromise = annoMatrix.fetch(...query); + } + const [categoryData, colorData] = await Promise.all([ + annoMatrix.fetch("obs", metadataField), + colorDataPromise, + ]); + + // our data + const column = categoryData.icol(0); + const colSchema = schema.annotations.obsByName[metadataField]; + const categorySummary = this.createCategorySummaryFromDfCol( + column, + colSchema + ); + return [categoryData, categorySummary, colorData]; + } + + updateColorTable(colorData) { + // color table, which may be null + const { schema, colors, metadataField } = this.props; + const { colorAccessor, userColors, colorMode } = colors; + return { + isColorAccessor: colorAccessor === metadataField, + colorAccessor, + colorMode, + colorTable: createColorTable( + colorMode, + colorAccessor, + colorData, + schema, + userColors + ), + }; + } + + toggleNone(categorySummary) { + const { dispatch, metadataField } = this.props; + dispatch( + actions.selectCategoricalAllMetadataAction( + "categorical metadata filter none of these", + metadataField, + categorySummary.allCategoryValues, + false + ) + ); + } + + toggleAll(categorySummary) { + const { dispatch, metadataField } = this.props; + dispatch( + actions.selectCategoricalAllMetadataAction( + "categorical metadata filter all of these", + metadataField, + categorySummary.allCategoryValues, + true + ) + ); + } + + render() { + const { + metadataField, + isExpanded, + categoricalSelection, + crossfilter, + colors, + annoMatrix, + isUserAnno, + } = this.props; + + const checkboxID = `category-select-${metadataField}`; + + return ( + + + + + + + {(error) => ( + + )} + + + {(asyncProps) => { + const { + colorAccessor, + colorTable, + colorData, + categoryData, + categorySummary, + isColorAccessor, + handleCategoryToggleAllClick, + } = asyncProps; + const selectionState = this.getSelectionState(categorySummary); + return ( + + ); + }} + + + + ); + } +} + +export default Category; + +const StillLoading = ({ metadataField, checkboxID }) => + /* + We are still loading this category, so render a "busy" signal. + */ + ( +
+
+
+ + + + {metadataField} + + +
+
+
+
+
+ ) +; + +const ErrorLoading = ({ metadataField, error }) => { + console.error(error); // log error to console as it is unexpected. + return ( +
+ + {`Failure loading ${metadataField}`} + +
+ ); +}; + +const CategoryHeader = React.memo( + ({ + metadataField, + checkboxID, + isUserAnno, + isColorAccessor, + isExpanded, + selectionState, + onColorChangeClick, + onCategoryMenuClick, + onCategoryMenuKeyPress, + onCategoryToggleAllClick, + }) => { + /* + Render category name and controls (eg, color-by button). + */ + const checkboxRef = useRef(null); + + useEffect(() => { + checkboxRef.current.indeterminate = selectionState === "some"; + }, [checkboxRef.current, selectionState]); + + return ( + <> +
+ + + + + {metadataField} + + + {isExpanded ? ( + + ) : ( + + )} + +
+ {} + {} +
+ + + + + +
+ + ); + } +); + +const CategoryRender = React.memo( + ({ + metadataField, + checkboxID, + isUserAnno, + isColorAccessor, + isExpanded, + selectionState, + categoryData, + categorySummary, + colorAccessor, + colorData, + colorTable, + onColorChangeClick, + onCategoryMenuClick, + onCategoryMenuKeyPress, + onCategoryToggleAllClick, + }) => { + /* + Render the core of the category, including checkboxes, controls, etc. + */ + const { numCategoryValues } = categorySummary; + const isSingularValue = !isUserAnno && numCategoryValues === 1; + + if (isSingularValue) { + /* + Entire category has a single value, special case. + */ + return null; + } + + /* + Otherwise, our normal multi-layout layout + */ + return ( +
+
+ +
+
+ { + /* values*/ + isExpanded ? ( + + ) : null + } +
+
+ ); + } +); + +const CategoryValueList = React.memo( + ({ + isUserAnno, + metadataField, + categoryData, + categorySummary, + colorAccessor, + colorData, + colorTable, + }) => { + const tuples = [...categorySummary.categoryValueIndices]; + + /* + Render the value list. If this is a user annotation, we use a flipper + animation, if read-only, we don't bother and save a few bits of perf. + */ + if (!isUserAnno) { + return ( + <> + {tuples.map(([value, index]) => ( + + ))} + + ); + } + + /* User annotation */ + const flipKey = tuples.map((t) => t[0]).join(""); + return ( + + {tuples.map(([value, index]) => ( + + + + ))} + + ); + } +); diff --git a/client/src/components/categorical/category/index.tsx b/client/src/components/categorical/category/index.tsx deleted file mode 100644 index 77d3265e..00000000 --- a/client/src/components/categorical/category/index.tsx +++ /dev/null @@ -1,724 +0,0 @@ -import React, { useRef, useEffect } from "react"; -import { connect, shallowEqual } from "react-redux"; -import { FaChevronRight, FaChevronDown } from "react-icons/fa"; -import { - AnchorButton, - Button, - Classes, - Position, - Tooltip, -} from "@blueprintjs/core"; -import { Flipper, Flipped } from "react-flip-toolkit"; -import Async from "react-async"; -import memoize from "memoize-one"; - -import Value from "../value"; -import AnnoMenu from "./annoMenuCategory"; -import AnnoDialogEditCategoryName from "./annoDialogEditCategoryName"; -import AnnoDialogAddLabel from "./annoDialogAddLabel"; -import Truncate from "../../util/truncate"; -import { CategoryCrossfilterContext } from "../categoryContext"; - -import * as globals from "../../../globals"; -import { createCategorySummaryFromDfCol } from "../../../util/stateManager/controlsHelpers"; -import { - createColorTable, - createColorQuery, -} from "../../../util/stateManager/colorHelpers"; -import actions from "../../../actions"; -import { Dataframe } from "../../../util/dataframe"; - -const LABEL_WIDTH = globals.leftSidebarWidth - 100; -const ANNO_BUTTON_WIDTH = 50; -const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state, ownProps) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const schema = (state as any).annoMatrix?.schema; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message - const { metadataField } = ownProps; - const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const categoricalSelection = (state as any).categoricalSelection?.[ - metadataField - ]; - return { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colors: (state as any).colors, - categoricalSelection, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - crossfilter: (state as any).obsCrossfilter, - isUserAnno, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, - }; -}) -class Category extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - static getSelectionState( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoricalSelection: any, - // @ts-expect-error ts-migrate(6133) FIXME: 'metadataField' is declared but its value is never... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categorySummary: any - ) { - // total number of categories in this dimension - const totalCatCount = categorySummary.numCategoryValues; - // number of selected options in this category - const selectedCatCount = categorySummary.categoryValues.reduce( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (res: any, label: any) => - categoricalSelection.get(label) ?? true ? res + 1 : res, - 0 - ); - return selectedCatCount === totalCatCount - ? "all" - : selectedCatCount === 0 - ? "none" - : "some"; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static watchAsync(props: any, prevProps: any) { - return !shallowEqual(props.watchProps, prevProps.watchProps); - } - - createCategorySummaryFromDfCol = memoize(createCategorySummaryFromDfCol); - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - getSelectionState(categorySummary: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message - const { categoricalSelection, metadataField } = this.props; - return Category.getSelectionState( - categoricalSelection, - metadataField, - categorySummary - ); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleColorChange = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - dispatch({ - type: "color by categorical metadata", - colorAccessor: metadataField, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleCategoryClick = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message - const { annotations, metadataField, onExpansionChange } = this.props; - const editingCategory = - annotations.isEditingCategoryName && - annotations.categoryBeingEdited === metadataField; - if (!editingCategory) { - onExpansionChange(metadataField); - } - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleCategoryKeyPress = (e: any) => { - if (e.key === "Enter") { - this.handleCategoryClick(); - } - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleToggleAllClick = (categorySummary: any) => { - const isChecked = this.getSelectionState(categorySummary); - if (isChecked === "all") { - this.toggleNone(categorySummary); - } else { - this.toggleAll(categorySummary); - } - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fetchAsyncProps = async (props: any) => { - const { annoMatrix, metadataField, colors } = props.watchProps; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message - const { crossfilter } = this.props; - - const [categoryData, categorySummary, colorData] = await this.fetchData( - annoMatrix, - metadataField, - colors - ); - - return { - categoryData, - categorySummary, - colorData, - crossfilter, - ...this.updateColorTable(colorData), - handleCategoryToggleAllClick: () => - this.handleToggleAllClick(categorySummary), - }; - }; - - async fetchData( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - annoMatrix: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colors: any - ): Promise< - [ - Dataframe, - ReturnType, - Dataframe | null - ] - > { - /* - fetch our data and the color-by data if appropriate, and then build a summary - of our category and a color table for the color-by annotation. - */ - const { schema } = annoMatrix; - const { colorAccessor, colorMode } = colors; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message - const { genesets } = this.props; - let colorDataPromise: Promise = Promise.resolve(null); - if (colorAccessor) { - const query = createColorQuery( - colorMode, - colorAccessor, - schema, - genesets - ); - if (query) colorDataPromise = annoMatrix.fetch(...query); - } - const [categoryData, colorData] = await Promise.all< - Dataframe, - Dataframe | null - >([annoMatrix.fetch("obs", metadataField), colorDataPromise]); - - // our data - const column = categoryData.icol(0); - const colSchema = schema.annotations.obsByName[metadataField]; - const categorySummary = this.createCategorySummaryFromDfCol( - column, - colSchema - ); - return [categoryData, categorySummary, colorData]; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -- - FIXME: disabled temporarily on migrate to TS. - updateColorTable(colorData: Dataframe|null) { - // color table, which may be null - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - const { schema, colors, metadataField } = this.props; - const { colorAccessor, userColors, colorMode } = colors; - return { - isColorAccessor: colorAccessor === metadataField, - colorAccessor, - colorMode, - colorTable: createColorTable( - colorMode, - colorAccessor, - colorData, - schema, - userColors - ), - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - toggleNone(categorySummary: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - dispatch( - actions.selectCategoricalAllMetadataAction( - "categorical metadata filter none of these", - metadataField, - categorySummary.allCategoryValues, - false - ) - ); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - toggleAll(categorySummary: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, metadataField } = this.props; - dispatch( - actions.selectCategoricalAllMetadataAction( - "categorical metadata filter all of these", - metadataField, - categorySummary.allCategoryValues, - true - ) - ); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type 'Read... Remove this comment to see the full error message - isExpanded, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message - categoricalSelection, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message - crossfilter, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message - colors, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message - annoMatrix, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message - isUserAnno, - } = this.props; - - const checkboxID = `category-select-${metadataField}`; - - return ( - - - - - - - {(error) => ( - - )} - - - {(asyncProps) => { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'u... Remove this comment to see the full error message - colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'unkn... Remove this comment to see the full error message - colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'unkno... Remove this comment to see the full error message - colorData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'un... Remove this comment to see the full error message - categoryData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message - categorySummary, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message - isColorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCategoryToggleAllClick' does not e... Remove this comment to see the full error message - handleCategoryToggleAllClick, - } = asyncProps; - const selectionState = this.getSelectionState(categorySummary); - return ( - - ); - }} - - - - ); - } -} - -export default Category; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const StillLoading = ({ metadataField, checkboxID }: any) => ( - /* - We are still loading this category, so render a "busy" signal. - */ -
-
-
- - - - {metadataField} - - -
-
-
-
-
-); -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const ErrorLoading = ({ metadataField, error }: any) => { - console.error(error); // log error to console as it is unexpected. - return ( -
- - {`Failure loading ${metadataField}`} - -
- ); -}; - -const CategoryHeader = React.memo( - ({ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'checkboxID' does not exist on type '{ ch... Remove this comment to see the full error message - checkboxID, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message - isUserAnno, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message - isColorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type '{ ch... Remove this comment to see the full error message - isExpanded, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionState' does not exist on type '... Remove this comment to see the full error message - selectionState, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onColorChangeClick' does not exist on ty... Remove this comment to see the full error message - onColorChangeClick, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuClick' does not exist on t... Remove this comment to see the full error message - onCategoryMenuClick, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message - onCategoryMenuKeyPress, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message - onCategoryToggleAllClick, - }) => { - /* - Render category name and controls (eg, color-by button). - */ - const checkboxRef = useRef(null); - - useEffect(() => { - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - checkboxRef.current.indeterminate = selectionState === "some"; - }, [checkboxRef.current, selectionState]); - - return ( - <> -
- - - - - {metadataField} - - - {isExpanded ? ( - - ) : ( - - )} - -
- {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; }' is not assignable t... Remove this comment to see the full error message */} - - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ metadataField: any; }' is not assignable t... Remove this comment to see the full error message */} - -
- - - - - -
- - ); - } -); - -const CategoryRender = React.memo( - ({ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'checkboxID' does not exist on type '{ ch... Remove this comment to see the full error message - checkboxID, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message - isUserAnno, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message - isColorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isExpanded' does not exist on type '{ ch... Remove this comment to see the full error message - isExpanded, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionState' does not exist on type '... Remove this comment to see the full error message - selectionState, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type '{ ... Remove this comment to see the full error message - categoryData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message - categorySummary, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type '{... Remove this comment to see the full error message - colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type '{ chi... Remove this comment to see the full error message - colorData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type '{ ch... Remove this comment to see the full error message - colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onColorChangeClick' does not exist on ty... Remove this comment to see the full error message - onColorChangeClick, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuClick' does not exist on t... Remove this comment to see the full error message - onCategoryMenuClick, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryMenuKeyPress' does not exist o... Remove this comment to see the full error message - onCategoryMenuKeyPress, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onCategoryToggleAllClick' does not exist... Remove this comment to see the full error message - onCategoryToggleAllClick, - }) => { - /* - Render the core of the category, including checkboxes, controls, etc. - */ - const { numCategoryValues } = categorySummary; - const isSingularValue = !isUserAnno && numCategoryValues === 1; - - if (isSingularValue) { - /* - Entire category has a single value, special case. - */ - return null; - } - - /* - Otherwise, our normal multi-layout layout - */ - return ( -
-
- -
-
- { - /* values*/ - isExpanded ? ( - - ) : null - } -
-
- ); - } -); - -const CategoryValueList = React.memo( - ({ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type '{ ch... Remove this comment to see the full error message - isUserAnno, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type '{ ... Remove this comment to see the full error message - categoryData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message - categorySummary, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type '{... Remove this comment to see the full error message - colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type '{ chi... Remove this comment to see the full error message - colorData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type '{ ch... Remove this comment to see the full error message - colorTable, - }) => { - const tuples = [...categorySummary.categoryValueIndices]; - - /* - Render the value list. If this is a user annotation, we use a flipper - animation, if read-only, we don't bother and save a few bits of perf. - */ - if (!isUserAnno) { - return ( - <> - {tuples.map(([value, index]) => ( - - ))} - - ); - } - - /* User annotation */ - const flipKey = tuples.map((t) => t[0]).join(""); - return ( - - {tuples.map(([value, index]) => ( - - - - ))} - - ); - } -); diff --git a/client/src/components/categorical/categoryContext.ts b/client/src/components/categorical/categoryContext.js similarity index 100% rename from client/src/components/categorical/categoryContext.ts rename to client/src/components/categorical/categoryContext.js diff --git a/client/src/components/categorical/index.tsx b/client/src/components/categorical/index.js similarity index 54% rename from client/src/components/categorical/index.tsx rename to client/src/components/categorical/index.js index 195675b2..160daa86 100644 --- a/client/src/components/categorical/index.tsx +++ b/client/src/components/categorical/index.js @@ -10,23 +10,13 @@ import LabelInput from "../labelInput"; import { labelPrompt } from "./labelUtil"; import actions from "../../actions"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - writableCategoriesEnabled: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.annotations ?? false, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userInfo: (state as any).userInfo, + writableCategoriesEnabled: state.config?.parameters?.annotations ?? false, + schema: state.annoMatrix?.schema, + userInfo: state.userInfo, })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Categories extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class Categories extends React.Component { + constructor(props) { super(props); this.state = { createAnnoModeActive: false, @@ -36,9 +26,7 @@ class Categories extends React.Component<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleCreateUserAnno = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleCreateUserAnno = (e) => { const { dispatch } = this.props; const { newCategoryText, categoryToDuplicate } = this.state; dispatch( @@ -55,12 +43,10 @@ class Categories extends React.Component<{}, State> { e.preventDefault(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleEnableAnnoMode = () => { this.setState({ createAnnoModeActive: true }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDisableAnnoMode = () => { this.setState({ createAnnoModeActive: false, @@ -69,58 +55,56 @@ class Categories extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleModalDuplicateCategorySelection = (d: any) => { + handleModalDuplicateCategorySelection = (d) => { this.setState({ categoryToDuplicate: d }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryNameError = (name: any) => { + categoryNameError = (name) => { /* - return false if this is a LEGAL/acceptable category name or NULL/empty string, - or return an error type. - */ + return false if this is a LEGAL/acceptable category name or NULL/empty string, + or return an error type. + */ + /* allow empty string */ if (name === "") return false; + /* - test for uniqueness against *all* annotation names, not just the subset - we render as categorical. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message + test for uniqueness against *all* annotation names, not just the subset + we render as categorical. + */ const { schema } = this.props; - const allCategoryNames = schema.annotations.obs.columns.map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (c: any) => c.name - ); + const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name); + /* check category name syntax */ const error = AnnotationsHelpers.annotationNameIsErroneous(name); if (error) { return error; } + /* disallow duplicates */ if (allCategoryNames.indexOf(name) !== -1) { return "duplicate"; } + /* otherwise, no error */ return false; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChange = (name: any) => { + handleChange = (name) => { this.setState({ newCategoryText: name }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleSelect = (name: any) => { + handleSelect = (name) => { this.setState({ newCategoryText: name }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - instruction = (name: any) => - labelPrompt(this.categoryNameError(name), "New, unique category name", ":"); + instruction = (name) => labelPrompt( + this.categoryNameError(name), + "New, unique category name", + ":" + ); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - onExpansionChange = (catName: any) => { + onExpansionChange = (catName) => { const { expandedCats } = this.state; if (expandedCats.has(catName)) { const _expandedCats = new Set(expandedCats); @@ -133,7 +117,6 @@ class Categories extends React.Component<{}, State> { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { createAnnoModeActive, @@ -141,13 +124,11 @@ class Categories extends React.Component<{}, State> { newCategoryText, expandedCats, } = this.state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'writableCategoriesEnabled' does not exis... Remove this comment to see the full error message const { writableCategoriesEnabled, schema, userInfo } = this.props; /* all names, sorted in display order. Will be rendered in this order */ - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - const allCategoryNames = ControlsHelpers.selectableCategoryNames( - schema - ).sort(); + const allCategoryNames = + ControlsHelpers.selectableCategoryNames(schema).sort(); + return (
{ }} > { handleCancel={this.handleDisableAnnoMode} annoInput={ { } annoSelect={ { /> } /> + {writableCategoriesEnabled ? (
{
) : null} + {/* READ ONLY CATEGORICAL FIELDS */} {/* this is duplicative but flat, could be abstracted */} - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS */} - {allCategoryNames.map((catName: any) => + {allCategoryNames.map((catName) => !schema.annotations.obsByName[catName].writable && (schema.annotations.obsByName[catName].categories?.length > 1 || !schema.annotations.obsByName[catName].categories) ? ( { ) : null )} {/* WRITEABLE FIELDS */} - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS */} - {allCategoryNames.map((catName: any) => + {allCategoryNames.map((catName) => schema.annotations.obsByName[catName].writable ? ( { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on type 'D... Remove this comment to see the full error message const { pointDilation, categoricalSelection } = state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type '{... Remove this comment to see the full error message const { metadataField, categorySummary, categoryIndex } = ownProps; const isDilated = pointDilation.metadataField === metadataField && @@ -57,35 +48,27 @@ type State = any; const isSelected = category.get(label) ?? true; return { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, + annotations: state.annotations, + schema: state.annoMatrix?.schema, isDilated, isSelected, label, }; }) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class CategoryValue extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class CategoryValue extends React.Component { + constructor(props) { super(props); this.state = { editedLabelText: this.currentLabelAsString(), }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - componentDidUpdate(prevProps: {}) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message + componentDidUpdate(prevProps) { const { metadataField, categoryIndex, categorySummary } = this.props; if ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (prevProps as any).metadataField !== metadataField || - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (prevProps as any).categoryIndex !== categoryIndex || // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (prevProps as any).categorySummary !== categorySummary + prevProps.metadataField !== metadataField || + prevProps.categoryIndex !== categoryIndex || + prevProps.categorySummary !== categorySummary ) { // eslint-disable-next-line react/no-did-update-set-state --- adequately checked to prevent looping this.setState({ @@ -95,31 +78,23 @@ class CategoryValue extends React.Component<{}, State> { } // If coloring by and this isn't the colorAccessor and it isn't being edited - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. get shouldRenderStackedBarOrHistogram() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message const { colorAccessor, isColorBy, annotations } = this.props; return !!colorAccessor && !isColorBy && !annotations.isEditingLabelName; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDeleteValue = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, label } = this.props; dispatch(actions.annotationDeleteLabelFromCategory(metadataField, label)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleAddCurrentSelectionToThisLabel = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, label } = this.props; dispatch(actions.annotationLabelCurrentSelection(metadataField, label)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleEditValue = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleEditValue = (e) => { const { dispatch, metadataField, label } = this.props; const { editedLabelText } = this.state; this.cancelEditMode(); @@ -133,9 +108,7 @@ class CategoryValue extends React.Component<{}, State> { e.preventDefault(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleCreateArbitraryLabel = (txt: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleCreateArbitraryLabel = (txt) => { const { dispatch, metadataField, label } = this.props; this.cancelEditMode(); dispatch( @@ -143,21 +116,15 @@ class CategoryValue extends React.Component<{}, State> { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - labelNameError = (name: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message + labelNameError = (name) => { const { metadataField, schema } = this.props; if (name === this.currentLabelAsString()) return false; return isLabelErroneous(name, metadataField, schema); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - instruction = (label: any) => - labelPrompt(this.labelNameError(label), "New, unique label", ":"); + instruction = (label) => labelPrompt(this.labelNameError(label), "New, unique label", ":"); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. activateEditLabelMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, categoryIndex, label } = this.props; dispatch({ type: "annotation: activate edit label mode", @@ -167,9 +134,7 @@ class CategoryValue extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. cancelEditMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, categoryIndex, label } = this.props; this.setState({ editedLabelText: this.currentLabelAsString(), @@ -182,18 +147,9 @@ class CategoryValue extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. toggleOff = () => { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - dispatch, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message - categoryIndex, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message - categorySummary, - } = this.props; + const { dispatch, metadataField, categoryIndex, categorySummary } = + this.props; const label = categorySummary.categoryValues[categoryIndex]; dispatch( actions.selectCategoricalMetadataAction( @@ -206,8 +162,7 @@ class CategoryValue extends React.Component<{}, State> { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - shouldComponentUpdate = (nextProps: any, nextState: any) => { + shouldComponentUpdate = (nextProps, nextState) => { /* Checks to see if at least one of the following changed: * world state @@ -218,7 +173,6 @@ class CategoryValue extends React.Component<{}, State> { If and only if true, update the component */ const { props, state } = this; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message const { categoryIndex, categorySummary, isSelected } = props; const { categoryIndex: newCategoryIndex, @@ -231,15 +185,10 @@ class CategoryValue extends React.Component<{}, State> { const labelChanged = label !== newLabel; const valueSelectionChange = isSelected !== newIsSelected; - const colorAccessorChange = - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (props as any).colorAccessor !== nextProps.colorAccessor; - const annotationsChange = - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (props as any).annotations !== nextProps.annotations; + const colorAccessorChange = props.colorAccessor !== nextProps.colorAccessor; + const annotationsChange = props.annotations !== nextProps.annotations; const editingLabel = state.editedLabelText !== nextState.editedLabelText; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const dilationChange = (props as any).isDilated !== nextProps.isDilated; + const dilationChange = props.isDilated !== nextProps.isDilated; const count = categorySummary.categoryValueCounts[categoryIndex]; const newCount = newCategorySummary.categoryValueCounts[newCategoryIndex]; @@ -250,8 +199,7 @@ class CategoryValue extends React.Component<{}, State> { // if any one changes, but only for the currently colored-by category. const colorMightHaveChanged = nextProps.colorAccessor === nextProps.metadataField && - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (props as any).categorySummary !== nextProps.categorySummary; + props.categorySummary !== nextProps.categorySummary; return ( labelChanged || @@ -265,18 +213,9 @@ class CategoryValue extends React.Component<{}, State> { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. toggleOn = () => { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - dispatch, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message - categoryIndex, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message - categorySummary, - } = this.props; + const { dispatch, metadataField, categoryIndex, categorySummary } = + this.props; const label = categorySummary.categoryValues[categoryIndex]; dispatch( actions.selectCategoricalMetadataAction( @@ -289,9 +228,7 @@ class CategoryValue extends React.Component<{}, State> { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleMouseEnter = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, categoryIndex, label } = this.props; dispatch({ type: "category value mouse hover start", @@ -301,9 +238,7 @@ class CategoryValue extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleMouseExit = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, metadataField, categoryIndex, label } = this.props; dispatch({ type: "category value mouse hover end", @@ -313,32 +248,23 @@ class CategoryValue extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleTextChange = (text: any) => { + handleTextChange = (text) => { this.setState({ editedLabelText: text }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChoice = (e: any) => { + handleChoice = (e) => { /* Blueprint Suggest format */ this.setState({ editedLabelText: e.target }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. createHistogramBins = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - categoryData: Dataframe, - // @ts-expect-error ts-migrate(6133) FIXME: 'colorAccessor' is declared but its value is never... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorAccessor: any, - colorData: Dataframe, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryValue: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - width: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - height: any + metadataField, + categoryData, + colorAccessor, + colorData, + categoryValue, + width, + height ) => { /* Knowing that colorScale is based off continuous data, @@ -347,17 +273,17 @@ class CategoryValue extends React.Component<{}, State> { */ const groupBy = categoryData.col(metadataField); const col = colorData.icol(0); - const range = col.summarizeContinuous(); + const range = col.summarize(); - const histogramMap = col.histogramContinuousBy( + const histogramMap = col.histogram( 50, [range.min, range.max], groupBy - ); + ); /* Because the signature changes we really need different names for histogram to differentiate signatures */ const bins = histogramMap.has(categoryValue) - ? histogramMap.get(categoryValue) as ContinuousHistogram - : new Array(50).fill(0); + ? histogramMap.get(categoryValue) + : new Array(50).fill(0); const xScale = d3.scaleLinear().domain([0, bins.length]).range([0, width]); @@ -372,23 +298,15 @@ class CategoryValue extends React.Component<{}, State> { }; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. createStackedGraphBins = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - metadataField: any, - categoryData: Dataframe, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorAccessor: any, - colorData: Dataframe, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - categoryValue: any, - // @ts-expect-error ts-migrate(6133) FIXME: 'colorTable' is declared but its value is never re... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorTable: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - schema: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - width: any + metadataField, + categoryData, + colorAccessor, + colorData, + categoryValue, + colorTable, + schema, + width ) => { /* Knowing that the color scale is based off of categorical data, @@ -398,7 +316,7 @@ class CategoryValue extends React.Component<{}, State> { const groupBy = categoryData.col(metadataField); const occupancyMap = colorData .col(colorAccessor) - .histogramCategoricalBy(groupBy); + .histogramCategorical(groupBy); const occupancy = occupancyMap.get(categoryValue); @@ -425,19 +343,16 @@ class CategoryValue extends React.Component<{}, State> { return null; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. currentLabelAsString() { return _currentLabelAsString(this.props); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isAddCurrentSelectionDisabled(crossfilter: any, category: any, value: any) { + isAddCurrentSelectionDisabled(crossfilter, category, value) { /* disable "add current selection to label", if one of the following is true: 1. no cells are selected 2. all currently selected cells already have this label, on this category */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message const { categoryData } = this.props; // 1. no cells selected? @@ -455,22 +370,14 @@ class CategoryValue extends React.Component<{}, State> { return false; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderMiniStackedBar = () => { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message categoryData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message colorData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message schema, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message label, } = this.props; const isColorBy = metadataField === colorAccessor; @@ -508,29 +415,20 @@ class CategoryValue extends React.Component<{}, State> { domain, occupancy, }} - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ height: number; width: number; colorTable:... Remove this comment to see the full error message height={STACKED_BAR_HEIGHT} width={STACKED_BAR_WIDTH} /> ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderMiniHistogram = () => { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message colorData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message categoryData, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message schema, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message label, } = this.props; const colorScale = colorTable?.scale; @@ -565,7 +463,6 @@ class CategoryValue extends React.Component<{}, State> { yScale, bins, }} - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ obsOrVarContinuousFieldDisplayName: any; d... Remove this comment to see the full error message obsOrVarContinuousFieldDisplayName={colorAccessor} domainLabel={label} height={STACKED_BAR_HEIGHT} @@ -574,28 +471,17 @@ class CategoryValue extends React.Component<{}, State> { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message metadataField, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryIndex' does not exist on type 'R... Remove this comment to see the full error message categoryIndex, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isUserAnno' does not exist on type 'Read... Remove this comment to see the full error message isUserAnno, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annotations' does not exist on type 'Rea... Remove this comment to see the full error message annotations, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isDilated' does not exist on type 'Reado... Remove this comment to see the full error message isDilated, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isSelected' does not exist on type 'Read... Remove this comment to see the full error message isSelected, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categorySummary' does not exist on type ... Remove this comment to see the full error message categorySummary, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type 'Readonly<... Remove this comment to see the full error message label, } = this.props; const colorScale = colorTable?.scale; @@ -691,7 +577,6 @@ class CategoryValue extends React.Component<{}, State> { { {editModeActive ? (
{ handleCancel={this.cancelEditMode} annoInput={ ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, + schema: state.annoMatrix?.schema, })) class Occupancy extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - canvas: any; - _WIDTH = 100; _HEIGHT = 11; - createHistogram = (): void => { + createHistogram = () => { /* - Knowing that colorScale is based off continuous data, - createHistogram fetches the continuous data in relation to the cells relevant to the category value. - It then separates that data into 50 bins for drawing the mini-histogram - */ - const { metadataField, categoryData, colorData, categoryValue } = this - .props as { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message - metadataField; - categoryData: Dataframe; - colorData: Dataframe; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryValue' does not exist on type 'R... Remove this comment to see the full error message - categoryValue; - }; + Knowing that colorScale is based off continous data, + createHistogram fetches the continous data in relation to the cells releveant to the catagory value. + It then seperates that data into 50 bins for drawing the mini-histogram + */ + const { metadataField, categoryData, colorData, categoryValue } = + this.props; + if (!this.canvas) return; + const groupBy = categoryData.col(metadataField); const col = colorData.icol(0); - const range = col.summarizeContinuous(); - const histogramMap = col.histogramContinuousBy( + const range = col.summarize(); + + const histogramMap = col.histogram( 50, [range.min, range.max], groupBy - ); + ); /* Because the signature changes we really need different names for histogram to differentiate signatures */ + const bins = histogramMap.has(categoryValue) - ? (histogramMap.get(categoryValue) as number[]) + ? histogramMap.get(categoryValue) : new Array(50).fill(0); + const xScale = d3 .scaleLinear() .domain([0, bins.length]) .range([0, this._WIDTH]); + const largestBin = Math.max(...bins); + const yScale = d3 .scaleLinear() .domain([0, largestBin]) .range([0, this._HEIGHT]); + const ctx = this.canvas.getContext("2d"); + ctx.fillStyle = "#000"; + let x; let y; + const rectWidth = this._WIDTH / bins.length; + for (let i = 0, { length } = bins; i < length; i += 1) { x = xScale(i); y = yScale(bins[i]); @@ -71,12 +69,12 @@ class Occupancy extends React.PureComponent { } }; - createOccupancyStack = (): void => { + createOccupancyStack = () => { /* - Knowing that the color scale is based off of catagorical data, - createOccupancyStack obtains a map showing the number if cells per colored value - Using the colorScale a stack of colored bars is drawn representing the map - */ + Knowing that the color scale is based off of catagorical data, + createOccupancyStack obtains a map showing the number if cells per colored value + Using the colorScale a stack of colored bars is drawn representing the map + */ const { metadataField, categoryData, @@ -85,28 +83,20 @@ class Occupancy extends React.PureComponent { colorTable, schema, colorData, - } = this.props as { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - metadataField: any; - categoryData: Dataframe; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorAccessor: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoryValue: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorTable: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any; - colorData: Dataframe; - }; + } = this.props; const { scale: colorScale } = colorTable; + const ctx = this.canvas?.getContext("2d"); + if (!ctx) return; + const groupBy = categoryData.col(metadataField); const occupancyMap = colorData .col(colorAccessor) - .histogramCategoricalBy(groupBy); + .histogramCategorical(groupBy); + const occupancy = occupancyMap.get(categoryValue); + if (occupancy && occupancy.size > 0) { // not all categories have occupancy, so occupancy may be undefined. const x = d3 @@ -116,15 +106,18 @@ class Occupancy extends React.PureComponent { .range([0, this._WIDTH]); const categories = schema.annotations.obsByName[colorAccessor]?.categories; + let currentOffset = 0; const dfColumn = colorData.col(colorAccessor); const categoryValues = dfColumn.summarizeCategorical().categories; + let o; let scaledValue; let value; + for (let i = 0, { length } = categoryValues; i < length; i += 1) { value = categoryValues[i]; - o = occupancy.get(value) as number; + o = occupancy.get(value); scaledValue = x(o); ctx.fillStyle = o ? colorScale(categories.indexOf(value)) @@ -135,13 +128,12 @@ class Occupancy extends React.PureComponent { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message const { colorAccessor, categoryValue, colorByIsCategorical } = this.props; const { canvas } = this; if (canvas) canvas.getContext("2d").clearRect(0, 0, this._WIDTH, this._HEIGHT); + return ( ({ + 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 ( +
+ {allContinuousNames.map((key, zebra) => ( + + ))} +
+ ); + } +} + +export default Continuous; diff --git a/client/src/components/continuous/continuous.tsx b/client/src/components/continuous/continuous.tsx deleted file mode 100644 index 1ca9066c..00000000 --- a/client/src/components/continuous/continuous.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* rc slider https://www.npmjs.com/package/rc-slider */ - -import React from "react"; -import { connect } from "react-redux"; -import HistogramBrush from "../brushableHistogram"; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, -})) -class Continuous extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - /* initial value for iterator to simulate index, ranges is an object */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - const { schema } = this.props; - if (!schema) return null; - const obsIndex = schema.annotations.obs.index; - const allContinuousNames = schema.annotations.obs.columns - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((col: any) => col.type === "int32" || col.type === "float32") - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((col: any) => col.name !== obsIndex) - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .filter((col: any) => !col.writable) // skip user annotations - they will be treated as categorical - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .map((col: any) => col.name); - return ( -
- {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {allContinuousNames.map((key: any, zebra: any) => ( - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - - ))} -
- ); - } -} - -export default Continuous; diff --git a/client/src/components/continuous/setupParallelCoordinates.ts b/client/src/components/continuous/setupParallelCoordinates.js similarity index 64% rename from client/src/components/continuous/setupParallelCoordinates.ts rename to client/src/components/continuous/setupParallelCoordinates.js index c09d6646..56e5c5fb 100644 --- a/client/src/components/continuous/setupParallelCoordinates.ts +++ b/client/src/components/continuous/setupParallelCoordinates.js @@ -5,8 +5,7 @@ ******************************************/ import * as d3 from "d3"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const setupParallelCoordinates = (width: any, height: any, margin: any) => { +const setupParallelCoordinates = (width, height, margin) => { const container = d3.select("#parcoords"); const svg = container @@ -25,15 +24,10 @@ const setupParallelCoordinates = (width: any, height: any, margin: any) => { .style("margin-top", `${margin.top}px`) .style("margin-left", `${margin.left}px`); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. const ctx = canvas.node().getContext("2d"); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. ctx.globalCompositeOperation = "darken"; - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. ctx.globalAlpha = 0.15; - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. ctx.lineWidth = 1.5; - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. ctx.scale(devicePixelRatio, devicePixelRatio); return { diff --git a/client/src/components/continuous/util.js b/client/src/components/continuous/util.js new file mode 100644 index 00000000..8b05d940 --- /dev/null +++ b/client/src/components/continuous/util.js @@ -0,0 +1,49 @@ +import each from "lodash.foreach"; +import * as d3 from "d3"; + +const paddingRight = 120; +const continuousChartWidth = 1200; + +export const margin = { top: 66, right: 110, bottom: 20, left: 60 }; +export const width = + continuousChartWidth - margin.left - margin.right - paddingRight; +export const height = 340 - margin.top - margin.bottom; +export const innerHeight = height - 2; + +export const devicePixelRatio = window.devicePixelRatio || 1; + +export const createDimensions = (data) => { + const newArr = []; + each(data, (value, key) => { + if (value.range) { + newArr.push({ + key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */, + type: { + within: (d, extent, dim) => + extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1], + }, + scale: d3 + .scaleSqrt() + .range([innerHeight, 0]) + .domain([0, value.range.max]), + }); + } + }); + return newArr; +}; + +export const yAxis = d3.axisLeft(); + +export const brushstart = () => { + d3.event.sourceEvent.stopPropagation(); +}; + +// Unused. +// export const d3_functor = v => (typeof v === "function" ? v : () => v); +export const project = (d, dimensions, xscale) => + dimensions.map((p, i) => { + // check if data element has property and contains a value + if (!(p.key in d) || d[p.key] === null) return null; + + return [xscale(i), p.scale(d[p.key])]; + }); diff --git a/client/src/components/continuous/util.ts b/client/src/components/continuous/util.ts deleted file mode 100644 index 8bda22d6..00000000 --- a/client/src/components/continuous/util.ts +++ /dev/null @@ -1,57 +0,0 @@ -import each from "lodash.foreach"; -import * as d3 from "d3"; - -const paddingRight = 120; -const continuousChartWidth = 1200; - -export const margin = { top: 66, right: 110, bottom: 20, left: 60 }; -export const width = - continuousChartWidth - margin.left - margin.right - paddingRight; -export const height = 340 - margin.top - margin.bottom; -export const innerHeight = height - 2; - -export const devicePixelRatio = window.devicePixelRatio || 1; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const createDimensions = (data: any) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const newArr: any = []; - each(data, (value, key) => { - if (value.range) { - newArr.push({ - key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */, - type: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - within: (d: any, extent: any, dim: any) => - extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1], - }, - scale: d3 - .scaleSqrt() - .range([innerHeight, 0]) - .domain([0, value.range.max]), - }); - } - }); - return newArr; -}; - -// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. -export const yAxis = d3.axisLeft(); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export const brushstart = () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (d3 as any).event.sourceEvent.stopPropagation(); -}; - -// Unused. -// export const d3_functor = v => (typeof v === "function" ? v : () => v); -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const project = (d: any, dimensions: any, xscale: any) => - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dimensions.map((p: any, i: any) => { - // check if data element has property and contains a value - if (!(p.key in d) || d[p.key] === null) return null; - - return [xscale(i), p.scale(d[p.key])]; - }); diff --git a/client/src/components/continuousLegend/index.tsx b/client/src/components/continuousLegend/index.js similarity index 70% rename from client/src/components/continuousLegend/index.tsx rename to client/src/components/continuousLegend/index.js index bf8c365f..a4d1f1d3 100644 --- a/client/src/components/continuousLegend/index.tsx +++ b/client/src/components/continuousLegend/index.js @@ -9,8 +9,7 @@ import { } from "../../util/stateManager/colorHelpers"; // create continuous color legend -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => { +const continuous = (selectorId, colorScale, colorAccessor) => { const legendHeight = 200; const legendWidth = 80; const margin = { top: 10, right: 60, bottom: 10, left: 2 }; @@ -34,7 +33,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => { we flip the color scale as well [1, 0] instead of [0, 1] */ .node(); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. const ctx = canvas.getContext("2d"); const legendScale = d3 @@ -46,7 +44,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => { ]); /* we flip this to make viridis colors dark if high in the color scale */ // image data hackery based on http://bl.ocks.org/mbostock/048d21cf747371b11884f75ad896e5a5 - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. const image = ctx.createImageData(1, legendHeight); d3.range(legendHeight).forEach((i) => { const c = d3.rgb(colorScale(legendScale.invert(i))); @@ -55,7 +52,6 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => { image.data[4 * i + 2] = c.b; image.data[4 * i + 3] = 255; }); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. ctx.putImageData(image, 0, 0); // A simpler way to do the above, but possibly slower. keep in mind the legend @@ -109,30 +105,27 @@ const continuous = (selectorId: any, colorScale: any, colorAccessor: any) => { .text(colorAccessor); }; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colors: (state as any).colors, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, + annoMatrix: state.annoMatrix, + colors: state.colors, + genesets: state.genesets.genesets, })) class ContinuousLegend extends React.Component { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - async componentDidUpdate(prevProps: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + async componentDidUpdate(prevProps) { const { annoMatrix, colors, genesets } = this.props; if (!colors || !annoMatrix) return; + if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) { const { schema } = annoMatrix; const { colorMode, colorAccessor, userColors } = colors; + const colorQuery = createColorQuery( colorMode, colorAccessor, schema, genesets ); + const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null; const colorTable = createColorTable( colorMode, @@ -141,19 +134,19 @@ class ContinuousLegend extends React.Component { schema, userColors ); + const colorScale = colorTable.scale; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'range' does not exist on type '((idx: an... Remove this comment to see the full error message const range = colorScale?.range; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type '((idx: a... Remove this comment to see the full error message const [domainMin, domainMax] = colorScale?.domain?.() ?? [0, 0]; + /* always remove it, if it's not continuous we don't put it back. */ d3.select("#continuous_legend").selectAll("*").remove(); + if (colorAccessor && colorScale && range && domainMin < domainMax) { /* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */ if (range()[0][0] !== "#") { continuous( "#continuous_legend", - // @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type '((idx: a... Remove this comment to see the full error message d3.scaleSequential(interpolateCool).domain(colorScale.domain()), colorAccessor ); @@ -162,7 +155,6 @@ class ContinuousLegend extends React.Component { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { return (
({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: (state as any).layoutChoice, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - crossfilter: (state as any).obsCrossfilter, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Embedding extends React.PureComponent<{}, EmbeddingState> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + layoutChoice: state.layoutChoice, // TODO: really should clean up naming, s/layout/embedding/g + schema: state.annoMatrix?.schema, + crossfilter: state.obsCrossfilter, + })) +class Embedding extends React.PureComponent { + constructor(props) { super(props); this.state = {}; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleLayoutChoiceChange = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleLayoutChoiceChange = (e) => { const { dispatch } = this.props; dispatch(actions.layoutChoiceAction(e.currentTarget.value)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on type 'Re... Remove this comment to see the full error message const { layoutChoice, schema, crossfilter } = this.props; const { annoMatrix } = crossfilter; return ( @@ -111,23 +98,18 @@ class Embedding extends React.PureComponent<{}, EmbeddingState> { export default Embedding; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const loadAllEmbeddingCounts = async ({ annoMatrix, available }: any) => { +const loadAllEmbeddingCounts = async ({ annoMatrix, available }) => { const embeddings = await Promise.all( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - available.map((name: any) => annoMatrix.base().fetch("emb", name)) + available.map((name) => annoMatrix.base().fetch("emb", name)) ); - // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'name' implicitly has an 'any' type. return available.map((name, idx) => ({ embeddingName: name, embedding: embeddings[idx], - // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable... discreteCellIndex: getDiscreteCellEmbeddingRowIndex(embeddings[idx]), })); }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => { +const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }) => { const { available } = layoutChoice; const { data, error, isPending } = useAsync({ promiseFn: loadAllEmbeddingCounts, @@ -143,8 +125,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => { /* still loading, or errored out - just omit counts (TODO: spinner?) */ return ( - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {layoutChoice.available.map((name: any) => ( + {layoutChoice.available.map((name) => ( ))} @@ -153,8 +134,7 @@ const EmbeddingChoices = ({ onChange, annoMatrix, layoutChoice }: any) => { if (data) { return ( - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {data.map((summary: any) => { + {data.map((summary) => { const { discreteCellIndex, embeddingName } = summary; const sizeHint = `${discreteCellIndex.size()} cells`; return ( diff --git a/client/src/components/framework/container.tsx b/client/src/components/framework/container.js similarity index 64% rename from client/src/components/framework/container.tsx rename to client/src/components/framework/container.js index a50e25e6..db9e2e19 100644 --- a/client/src/components/framework/container.tsx +++ b/client/src/components/framework/container.js @@ -1,7 +1,6 @@ import React from "react"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -function Container(props: any) { +function Container(props) { const { children } = props; return (
{ +const Logo = (props) => { const { size } = props; return ( diff --git a/client/src/components/framework/toasters.js b/client/src/components/framework/toasters.js new file mode 100644 index 00000000..29e15cdf --- /dev/null +++ b/client/src/components/framework/toasters.js @@ -0,0 +1,52 @@ +import { Position, Toaster, Intent } from "@blueprintjs/core"; + +/** Singleton toaster instance. Create separate instances for different options. */ + +const ToastTopCenter = Toaster.create({ + className: "recipe-toaster", + position: Position.TOP, + maxToasts: 4, +}); + +/* +A "user" error - eg, bad input +*/ +export const postUserErrorToast = (message) => + ToastTopCenter.show({ message, intent: Intent.WARNING }); + +/* +A toast the user must dismiss manually, because they need to act on its information, +ie., 8 bulk add genes out of 40 were bad. Manually see which ones and fix. +*/ +export const keepAroundErrorToast = (message) => + ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING }); + +/* +a hard network error +*/ +export const postNetworkErrorToast = (message, key = undefined) => + ToastTopCenter.show( + { + message, + timeout: 30000, + intent: Intent.DANGER, + }, + key + ); + +/* +Async message to user +*/ +export const postAsyncSuccessToast = (message) => + ToastTopCenter.show({ + message, + timeout: 10000, + intent: Intent.SUCCESS, + }); + +export const postAsyncFailureToast = (message) => + ToastTopCenter.show({ + message, + timeout: 10000, + intent: Intent.WARNING, + }); diff --git a/client/src/components/framework/toasters.ts b/client/src/components/framework/toasters.ts deleted file mode 100644 index ce41956e..00000000 --- a/client/src/components/framework/toasters.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Position, Toaster, Intent } from "@blueprintjs/core"; - -/** Singleton toaster instance. Create separate instances for different options. */ - -const ToastTopCenter = Toaster.create({ - className: "recipe-toaster", - position: Position.TOP, - maxToasts: 4, -}); - -/* -A "user" error - eg, bad input -*/ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const postUserErrorToast = (message: any) => - ToastTopCenter.show({ message, intent: Intent.WARNING }); - -/* -A toast the user must dismiss manually, because they need to act on its information, -ie., 8 bulk add genes out of 40 were bad. Manually see which ones and fix. -*/ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const keepAroundErrorToast = (message: any) => - ToastTopCenter.show({ message, timeout: 0, intent: Intent.WARNING }); - -/* -a hard network error -*/ -export const postNetworkErrorToast = ( - message: string, - key: string | undefined = undefined -): string => - ToastTopCenter.show( - { - message, - timeout: 30000, - intent: Intent.DANGER, - }, - key - ); - -/* -Async message to user -*/ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const postAsyncSuccessToast = (message: any) => - ToastTopCenter.show({ - message, - timeout: 10000, - intent: Intent.SUCCESS, - }); - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export const postAsyncFailureToast = (message: any) => - ToastTopCenter.show({ - message, - timeout: 10000, - intent: Intent.WARNING, - }); diff --git a/client/src/components/geneExpression/gene.tsx b/client/src/components/geneExpression/gene.js similarity index 56% rename from client/src/components/geneExpression/gene.tsx rename to client/src/components/geneExpression/gene.js index 912aace6..47efc6cd 100644 --- a/client/src/components/geneExpression/gene.tsx +++ b/client/src/components/geneExpression/gene.js @@ -9,51 +9,34 @@ import actions from "../../actions"; const MINI_HISTOGRAM_WIDTH = 110; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state, ownProps) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'gene' does not exist on type '{}'. const { gene } = ownProps; return { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - isColorAccessor: (state as any).colors.colorAccessor === gene, - isScatterplotXXaccessor: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).controls.scatterplotXXaccessor === gene, - isScatterplotYYaccessor: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).controls.scatterplotYYaccessor === gene, + isColorAccessor: state.colors.colorAccessor === gene, + isScatterplotXXaccessor: state.controls.scatterplotXXaccessor === gene, + isScatterplotYYaccessor: state.controls.scatterplotYYaccessor === gene, }; }) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Gene extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class Gene extends React.Component { + constructor(props) { super(props); this.state = { geneIsExpanded: false, }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. onColorChangeClick = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, gene } = this.props; dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(gene)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleGeneExpandClick = () => { const { geneIsExpanded } = this.state; this.setState({ geneIsExpanded: !geneIsExpanded }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleSetGeneAsScatterplotX = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, gene } = this.props; dispatch({ type: "set scatterplot x", @@ -61,9 +44,7 @@ class Gene extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleSetGeneAsScatterplotY = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, gene } = this.props; dispatch({ type: "set scatterplot y", @@ -71,29 +52,19 @@ class Gene extends React.Component<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDeleteGeneFromSet = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, gene, geneset } = this.props; dispatch(actions.genesetDeleteGenes(geneset, [gene])); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'gene' does not exist on type 'Readonly<{... Remove this comment to see the full error message gene, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'geneDescription' does not exist on type ... Remove this comment to see the full error message geneDescription, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isColorAccessor' does not exist on type ... Remove this comment to see the full error message isColorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotXXaccessor' does not exist ... Remove this comment to see the full error message isScatterplotXXaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isScatterplotYYaccessor' does not exist ... Remove this comment to see the full error message isScatterplotYYaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'quickGene' does not exist on type 'Reado... Remove this comment to see the full error message quickGene, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'removeGene' does not exist on type 'Read... Remove this comment to see the full error message removeGene, } = this.props; const { geneIsExpanded } = this.state; @@ -113,7 +84,6 @@ class Gene extends React.Component<{}, State> { >
{
{!geneIsExpanded ? ( { />
- {/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */} {geneIsExpanded && }
); diff --git a/client/src/components/geneExpression/geneSet.tsx b/client/src/components/geneExpression/geneSet.js similarity index 68% rename from client/src/components/geneExpression/geneSet.tsx rename to client/src/components/geneExpression/geneSet.js index bc26382e..13bc22b1 100644 --- a/client/src/components/geneExpression/geneSet.tsx +++ b/client/src/components/geneExpression/geneSet.js @@ -9,28 +9,20 @@ import HistogramBrush from "../brushableHistogram"; import { diffexpPopNamePrefix1, diffexpPopNamePrefix2 } from "../../globals"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class GeneSet extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class GeneSet extends React.Component { + constructor(props) { super(props); this.state = { isOpen: false, }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. onGenesetMenuClick = () => { const { isOpen } = this.state; this.setState({ isOpen: !isOpen }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderGenes() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'setName' does not exist on type 'Readonl... Remove this comment to see the full error message const { setName, setGenes } = this.props; const setGenesNames = [...setGenes.keys()]; return ( @@ -40,7 +32,6 @@ class GeneSet extends React.Component<{}, State> { return ( { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'setName' does not exist on type 'Readonl... Remove this comment to see the full error message const { setName, genesetDescription, setGenes } = this.props; const { isOpen } = this.state; const genesetNameLengthVisible = 150; /* this magic number determines how much of a long geneset name we see */ @@ -76,7 +65,6 @@ class GeneSet extends React.Component<{}, State> { > { )}
- {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ isOpen: any; genesetsEditable: true; genes... Remove this comment to see the full error message */}
@@ -131,7 +118,6 @@ class GeneSet extends React.Component<{}, State> {
{isOpen && !genesetIsEmpty && ( { )} {isOpen && !genesetIsEmpty && this.renderGenes()} diff --git a/client/src/components/geneExpression/index.tsx b/client/src/components/geneExpression/index.js similarity index 50% rename from client/src/components/geneExpression/index.tsx rename to client/src/components/geneExpression/index.js index 6f711a32..735c0d60 100644 --- a/client/src/components/geneExpression/index.tsx +++ b/client/src/components/geneExpression/index.js @@ -7,33 +7,23 @@ import GeneSet from "./geneSet"; import QuickGene from "./quickGene"; import CreateGenesetDialogue from "./menus/createGenesetDialogue"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class GeneExpression extends React.Component<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + genesets: state.genesets.genesets, + })) +class GeneExpression extends React.Component { + constructor(props) { super(props); this.state = { geneSetsExpanded: true }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderGeneSets = () => { const sets = []; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message const { genesets } = this.props; for (const [name, geneset] of genesets) { sets.push( { return sets; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleActivateCreateGenesetMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch } = this.props; const { geneSetsExpanded } = this.state; dispatch({ type: "geneset: activate add new geneset mode" }); if (!geneSetsExpanded) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - this.setState((state: any) => ({ ...state, geneSetsExpanded: true })); + this.setState((state) => ({ ...state, geneSetsExpanded: true })); } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleExpandGeneSets = () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - this.setState((state: any) => ({ - ...state, - geneSetsExpanded: !state.geneSetsExpanded, - })); + this.setState((state) => ({ ...state, geneSetsExpanded: !state.geneSetsExpanded })); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { geneSetsExpanded } = this.state; return ( @@ -80,7 +61,6 @@ class GeneExpression extends React.Component<{}, State> { >

({ + genesetsUI: state.genesetsUI, +})) +class AddGeneToGenesetDialogue extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + genesToAdd: "", + }; + } + + disableAddGeneMode = () => { + const { dispatch } = this.props; + dispatch({ + type: "geneset: disable add new genes mode", + }); + }; + + handleAddGeneToGeneSet = (e) => { + const { geneset, dispatch } = this.props; + const { genesToAdd } = this.state; + + const genesTmpHardcodedFormat = []; + + const genesArrayFromString = parseBulkGeneString(genesToAdd); + + genesArrayFromString.forEach((_gene) => { + genesTmpHardcodedFormat.push({ + geneSymbol: _gene, + }); + }); + + dispatch(actions.genesetAddGenes(geneset, genesTmpHardcodedFormat)); + dispatch({ + type: "geneset: disable add new genes mode", + }); + if (e) e.preventDefault(); + }; + + handleChange = (e) => { + this.setState({ genesToAdd: e }); + }; + + render() { + const { geneset, genesetsUI } = this.props; + const { genesToAdd } = this.state; + + return ( + <> + + } + handleSubmit={this.handleAddGeneToGeneSet} + handleCancel={this.disableAddGeneMode} + /> + + ); + } +} + +export default AddGeneToGenesetDialogue; diff --git a/client/src/components/geneExpression/menus/addGeneToGenesetDialogue.tsx b/client/src/components/geneExpression/menus/addGeneToGenesetDialogue.tsx deleted file mode 100644 index 204df743..00000000 --- a/client/src/components/geneExpression/menus/addGeneToGenesetDialogue.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import AnnoDialog from "../../annoDialog"; -import LabelInput from "../../labelInput"; -import parseBulkGeneString from "../../../util/parseBulkGeneString"; -import actions from "../../../actions"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetsUI: (state as any).genesetsUI, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class AddGeneToGenesetDialogue extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = { - genesToAdd: "", - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - disableAddGeneMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch({ - type: "geneset: disable add new genes mode", - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleAddGeneToGeneSet = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message - const { geneset, dispatch } = this.props; - const { genesToAdd } = this.state; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const genesTmpHardcodedFormat: any = []; - const genesArrayFromString = parseBulkGeneString(genesToAdd); - genesArrayFromString.forEach((_gene) => { - genesTmpHardcodedFormat.push({ - geneSymbol: _gene, - }); - }); - dispatch(actions.genesetAddGenes(geneset, genesTmpHardcodedFormat)); - dispatch({ - type: "geneset: disable add new genes mode", - }); - if (e) e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChange = (e: any) => { - this.setState({ genesToAdd: e }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message - const { geneset, genesetsUI } = this.props; - const { genesToAdd } = this.state; - return ( - <> - void; inputProps: { ... Remove this comment to see the full error message - onChange={this.handleChange} - inputProps={{ - "data-testid": "add-genes", - leftIcon: "manually-entered-data", - intent: "none", - autoFocus: true, - }} - newLabelMessage="New category" - /> - } - handleSubmit={this.handleAddGeneToGeneSet} - handleCancel={this.disableAddGeneMode} - /> - - ); - } -} - -export default AddGeneToGenesetDialogue; diff --git a/client/src/components/geneExpression/menus/addGenes.tsx b/client/src/components/geneExpression/menus/addGenes.js similarity index 67% rename from client/src/components/geneExpression/menus/addGenes.tsx rename to client/src/components/geneExpression/menus/addGenes.js index 0585d772..ca1833da 100644 --- a/client/src/components/geneExpression/menus/addGenes.tsx +++ b/client/src/components/geneExpression/menus/addGenes.js @@ -19,10 +19,8 @@ import { import { memoize } from "../../../util/dataframe/util"; import parseBulkGeneString from "../../../util/parseBulkGeneString"; -import { Dataframe } from "../../../util/dataframe"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => { +const renderGene = (fuzzySortResult, { handleClick, modifiers }) => { if (!modifiers.matchesPredicate) { return null; } @@ -35,8 +33,8 @@ const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => { disabled={modifiers.disabled} data-testid={`suggest-menu-item-${geneName}`} key={geneName} - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - onClick={(g: any /* this fires when user clicks a menu item */) => + onClick={(g) => + /* this fires when user clicks a menu item */ handleClick(g) } text={geneName} @@ -44,30 +42,20 @@ const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => { ); }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const filterGenes = (query: any, genes: any) => +const filterGenes = (query, genes) => /* fires on load, once, and then for each character typed into the input */ fuzzysort.go(query, genes, { limit: 5, threshold: -10000, // don't return bad results }); -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type AddGenesState = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenes: (state as any).controls.userDefinedGenes, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenesLoading: (state as any).controls.userDefinedGenesLoading, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class AddGenes extends React.Component<{}, AddGenesState> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + annoMatrix: state.annoMatrix, + userDefinedGenes: state.controls.userDefinedGenes, + userDefinedGenesLoading: state.controls.userDefinedGenesLoading, + })) +class AddGenes extends React.Component { + constructor(props) { super(props); this.state = { bulkAdd: "", @@ -78,20 +66,15 @@ class AddGenes extends React.Component<{}, AddGenesState> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount() { - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. this.updateState(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - componentDidUpdate(prevProps: {}) { + componentDidUpdate(prevProps) { this.updateState(prevProps); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleClick(g: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleClick(g) { const { dispatch, userDefinedGenes } = this.props; const { geneNames } = this.state; if (!g) return; @@ -111,8 +94,7 @@ class AddGenes extends React.Component<{}, AddGenesState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - _genesToUpper = (listGenes: any) => { + _genesToUpper = (listGenes) => { // Has to be a Map to preserve index const upperGenes = new Map(); for (let i = 0, { length } = listGenes; i < length; i += 1) { @@ -122,12 +104,10 @@ class AddGenes extends React.Component<{}, AddGenesState> { return upperGenes; }; - // eslint-disable-next-line react/sort-comp, @typescript-eslint/no-explicit-any -- memo requires a defined _genesToUpper - _memoGenesToUpper = memoize(this._genesToUpper, (arr: any) => arr); + // eslint-disable-next-line react/sort-comp -- memo requires a defined _genesToUpper + _memoGenesToUpper = memoize(this._genesToUpper, (arr) => arr); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleBulkAddClick = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, userDefinedGenes } = this.props; const { bulkAdd, geneNames } = this.state; @@ -177,9 +157,7 @@ class AddGenes extends React.Component<{}, AddGenesState> { return undefined; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - async updateState(prevProps: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + async updateState(prevProps) { const { annoMatrix } = this.props; if (!annoMatrix) return; if (annoMatrix !== prevProps?.annoMatrix) { @@ -188,7 +166,7 @@ class AddGenes extends React.Component<{}, AddGenesState> { this.setState({ status: "pending" }); try { - const df: Dataframe = await annoMatrix.fetch("var", varIndex); + const df = await annoMatrix.fetch("var", varIndex); this.setState({ status: "success", geneNames: df.col(varIndex).asArray(), @@ -200,7 +178,6 @@ class AddGenes extends React.Component<{}, AddGenesState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. placeholderGeneNames() { /* return a string containing gene name suggestions for use as a user hint. @@ -230,9 +207,7 @@ class AddGenes extends React.Component<{}, AddGenesState> { return "Apod, Cd74, ..."; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'userDefinedGenesLoading' does not exist ... Remove this comment to see the full error message const { userDefinedGenesLoading } = this.props; const { tab, bulkAdd, activeItem, status, geneNames } = this.state; @@ -288,10 +263,8 @@ class AddGenes extends React.Component<{}, AddGenesState> { this.handleClick(g); }} initialContent={} - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ "data-testid": string; }' is not assignabl... Remove this comment to see the full error message inputProps={{ "data-testid": "gene-search" }} inputValueRenderer={() => ""} - // @ts-expect-error ts-migrate(2322) FIXME: Type '(query: any, genes: any) => Fuzzysort.Result... Remove this comment to see the full error message itemListPredicate={filterGenes} onActiveItemChange={(item) => this.setState({ activeItem: item })} itemRenderer={renderGene} diff --git a/client/src/components/geneExpression/menus/createGenesetDialogue.tsx b/client/src/components/geneExpression/menus/createGenesetDialogue.js similarity index 56% rename from client/src/components/geneExpression/menus/createGenesetDialogue.tsx rename to client/src/components/geneExpression/menus/createGenesetDialogue.js index 28e35815..e5363868 100644 --- a/client/src/components/geneExpression/menus/createGenesetDialogue.tsx +++ b/client/src/components/geneExpression/menus/createGenesetDialogue.js @@ -7,26 +7,15 @@ import { Tooltip2 } from "@blueprintjs/popover2"; import LabelInput from "../../labelInput"; import actions from "../../../actions"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - obsCrossfilter: (state as any).obsCrossfilter, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetsUI: (state as any).genesetsUI, + annotations: state.annotations, + schema: state.annoMatrix?.schema, + obsCrossfilter: state.obsCrossfilter, + genesets: state.genesets.genesets, + genesetsUI: state.genesetsUI, })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class CreateGenesetDialogue extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class CreateGenesetDialogue extends React.PureComponent { + constructor(props) { super(props); this.state = { genesetName: "", @@ -35,9 +24,7 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - disableCreateGenesetMode = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + disableCreateGenesetMode = (e) => { const { dispatch } = this.props; this.setState({ genesetName: "", @@ -51,32 +38,30 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { if (e) e.preventDefault(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - createGeneset = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + createGeneset = (e) => { const { dispatch } = this.props; - const { - genesetName, - genesToPopulateGeneset, - genesetDescription, - } = this.state; + const { genesetName, genesToPopulateGeneset, genesetDescription } = + this.state; + dispatch({ type: "geneset: create", genesetName: genesetName.trim(), genesetDescription, }); if (genesToPopulateGeneset) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const genesTmpHardcodedFormat: any = []; + const genesTmpHardcodedFormat = []; + const genesArrayFromString = pull( uniq(genesToPopulateGeneset.split(/[ ,]+/)), "" ); + genesArrayFromString.forEach((_gene) => { genesTmpHardcodedFormat.push({ geneSymbol: _gene, }); }); + dispatch(actions.genesetAddGenes(genesetName, genesTmpHardcodedFormat)); } dispatch({ @@ -89,41 +74,34 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { e.preventDefault(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. genesetNameError = () => false; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChange = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message + handleChange = (e) => { const { genesets } = this.props; this.setState({ genesetName: e }); this.validate(e, genesets); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleGenesetInputChange = (e: any) => { + handleGenesetInputChange = (e) => { this.setState({ genesToPopulateGeneset: e }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleDescriptionInputChange = (e: any) => { + handleDescriptionInputChange = (e) => { this.setState({ genesetDescription: e }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - instruction = (genesetName: any, genesets: any) => - genesets.has(genesetName) + instruction = (genesetName, genesets) => genesets.has(genesetName) ? "Gene set name must be unique." : "New, unique gene set name"; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - validate = (genesetName: any, genesets: any) => { + validate = (genesetName, genesets) => { if (genesets.has(genesetName)) { this.setState({ nameErrorMessage: "There is already a geneset with that name", }); return false; } + if ( genesetName.length > 1 && // eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535 @@ -141,11 +119,10 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { return true; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { genesetName, nameErrorMessage } = this.state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetsUI' does not exist on type 'Read... Remove this comment to see the full error message const { genesetsUI, genesets } = this.props; + return ( <> {

{this.instruction(genesetName, genesets)}

void; inputProps: { ... Remove this comment to see the full error message onChange={this.handleChange} inputProps={{ "data-testid": "create-geneset-input", @@ -188,7 +164,6 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { gene set

void; inputProps: { ... Remove this comment to see the full error message onChange={this.handleDescriptionInputChange} inputProps={{ "data-testid": "add-geneset-description", @@ -204,7 +179,6 @@ class CreateGenesetDialogue extends React.PureComponent<{}, State> { gene set

void; inputProps: { ... Remove this comment to see the full error message onChange={this.handleGenesetInputChange} inputProps={{ "data-testid": "add-genes", diff --git a/client/src/components/geneExpression/menus/editGenesetNameDialogue.js b/client/src/components/geneExpression/menus/editGenesetNameDialogue.js new file mode 100644 index 00000000..b005aa82 --- /dev/null +++ b/client/src/components/geneExpression/menus/editGenesetNameDialogue.js @@ -0,0 +1,124 @@ +import React from "react"; +import { connect } from "react-redux"; +import AnnoDialog from "../../annoDialog"; +import LabelInput from "../../labelInput"; + +@connect((state) => ({ + annotations: state.annotations, + schema: state.annoMatrix?.schema, + obsCrossfilter: state.obsCrossfilter, + genesetsUI: state.genesetsUI, + genesets: state.genesets.genesets, +})) +class RenameGeneset extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + newGenesetName: props.parentGeneset, + newGenesetDescription: props.parentGenesetDescription, + }; + } + + disableEditGenesetNameMode = (e) => { + const { dispatch } = this.props; + this.setState({ + newGenesetName: "", + newGenesetDescription: "", + }); + dispatch({ + type: "geneset: disable rename geneset mode", + }); + if (e) e.preventDefault(); + }; + + renameGeneset = (e) => { + const { dispatch, genesetsUI } = this.props; + const { newGenesetName, newGenesetDescription } = this.state; + + dispatch({ + type: "geneset: update", + genesetName: genesetsUI.isEditingGenesetName, + update: { + genesetName: newGenesetName, + genesetDescription: newGenesetDescription, + }, + }); + dispatch({ + type: "geneset: disable rename geneset mode", + }); + e.preventDefault(); + }; + + genesetNameError = () => false; + + handleChange = (e) => { + this.setState({ newGenesetName: e }); + }; + + handleChangeDescription = (e) => { + this.setState({ newGenesetDescription: e }); + }; + + validate = (genesetName, genesets) => ( + !genesets.has(genesetName) && + // eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535 + genesetName.match(/^\s|[\u0000-\u001F\u007F-\uFFFF]|[ ]{2,}|^$|\s$/g) + ?.length + ); + + render() { + const { newGenesetName, newGenesetDescription } = this.state; + const { genesetsUI, parentGeneset, parentGenesetDescription, genesets } = + this.props; + + return ( + <> + + } + secondaryInstructions="Edit description" + secondaryInput={ + + } + handleSubmit={this.renameGeneset} + handleCancel={this.disableEditGenesetNameMode} + /> + + ); + } +} + +export default RenameGeneset; diff --git a/client/src/components/geneExpression/menus/editGenesetNameDialogue.tsx b/client/src/components/geneExpression/menus/editGenesetNameDialogue.tsx deleted file mode 100644 index cc183057..00000000 --- a/client/src/components/geneExpression/menus/editGenesetNameDialogue.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import AnnoDialog from "../../annoDialog"; -import LabelInput from "../../labelInput"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annotations: (state as any).annotations, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix?.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - obsCrossfilter: (state as any).obsCrossfilter, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetsUI: (state as any).genesetsUI, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class RenameGeneset extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGeneset' does not exist on type '{... Remove this comment to see the full error message - newGenesetName: props.parentGeneset, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGenesetDescription' does not exist... Remove this comment to see the full error message - newGenesetDescription: props.parentGenesetDescription, - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - disableEditGenesetNameMode = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - this.setState({ - newGenesetName: "", - newGenesetDescription: "", - }); - dispatch({ - type: "geneset: disable rename geneset mode", - }); - if (e) e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - renameGeneset = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, genesetsUI } = this.props; - const { newGenesetName, newGenesetDescription } = this.state; - dispatch({ - type: "geneset: update", - genesetName: genesetsUI.isEditingGenesetName, - update: { - genesetName: newGenesetName, - genesetDescription: newGenesetDescription, - }, - }); - dispatch({ - type: "geneset: disable rename geneset mode", - }); - e.preventDefault(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - genesetNameError = () => false; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChange = (e: any) => { - this.setState({ newGenesetName: e }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChangeDescription = (e: any) => { - this.setState({ newGenesetDescription: e }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - validate = (genesetName: any, genesets: any) => - !genesets.has(genesetName) && - // eslint-disable-next-line no-control-regex -- unicode 0-31 127-65535 - genesetName.match(/^\s|[\u0000-\u001F\u007F-\uFFFF]|[ ]{2,}|^$|\s$/g) - ?.length; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { newGenesetName, newGenesetDescription } = this.state; - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesetsUI' does not exist on type 'Read... Remove this comment to see the full error message - genesetsUI, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGeneset' does not exist on type 'Read... Remove this comment to see the full error message - parentGeneset, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'parentGenesetDescription' does not exist on type 'Read... Remove this comment to see the full error message - parentGenesetDescription, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Read... Remove this comment to see the full error message - genesets, - } = this.props; - return ( - <> - void; in... Remove this comment to see the full error message - label={newGenesetName} - onChange={this.handleChange} - inputProps={{ - "data-testid": "rename-geneset-modal", - leftIcon: "manually-entered-data", - intent: "none", - autoFocus: true, - }} - /> - } - secondaryInstructions="Edit description" - secondaryInput={ - void; in... Remove this comment to see the full error message - label={newGenesetDescription} - onChange={this.handleChangeDescription} - inputProps={{ "data-testid": "change geneset description" }} - intent="none" - autoFocus={false} - /> - } - handleSubmit={this.renameGeneset} - handleCancel={this.disableEditGenesetNameMode} - /> - - ); - } -} - -export default RenameGeneset; diff --git a/client/src/components/geneExpression/menus/genesetMenus.tsx b/client/src/components/geneExpression/menus/genesetMenus.js similarity index 61% rename from client/src/components/geneExpression/menus/genesetMenus.tsx rename to client/src/components/geneExpression/menus/genesetMenus.js index 251ea859..f9c128c4 100644 --- a/client/src/components/geneExpression/menus/genesetMenus.tsx +++ b/client/src/components/geneExpression/menus/genesetMenus.js @@ -17,27 +17,17 @@ import * as globals from "../../../globals"; import actions from "../../../actions"; import AddGeneToGenesetDialogue from "./addGeneToGenesetDialogue"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesetsUI: (state as any).genesetsUI, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorAccessor: (state as any).colors.colorAccessor, -})) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class GenesetMenus extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + genesetsUI: state.genesetsUI, + colorAccessor: state.colors.colorAccessor, + })) +class GenesetMenus extends React.PureComponent { + constructor(props) { super(props); this.state = {}; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. activateAddGeneToGenesetMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, geneset } = this.props; dispatch({ type: "geneset: activate add new genes mode", @@ -45,9 +35,7 @@ class GenesetMenus extends React.PureComponent<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. activateEditGenesetNameMode = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, geneset } = this.props; dispatch({ @@ -56,9 +44,7 @@ class GenesetMenus extends React.PureComponent<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleColorByEntireGeneset = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, geneset } = this.props; dispatch({ @@ -67,16 +53,12 @@ class GenesetMenus extends React.PureComponent<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDeleteGeneset = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, geneset } = this.props; dispatch(actions.genesetDelete(geneset)); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'geneset' does not exist on type 'Readonl... Remove this comment to see the full error message const { geneset, genesetsEditable, createText, colorAccessor } = this.props; const isColorBy = geneset === colorAccessor; @@ -100,7 +82,6 @@ class GenesetMenus extends React.PureComponent<{}, State> { minimal /> - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ geneset: any; }' is not assignable to type... Remove this comment to see the full error message */} { +const usePrevious = (value) => { const ref = useRef(); useEffect(() => { ref.current = value; @@ -20,40 +18,34 @@ const usePrevious = (value: any) => { return ref.current; }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. function QuickGene() { const dispatch = useDispatch(); const [isExpanded, setIsExpanded] = useState(true); - const [geneNames, setGeneNames] = useState([] as DataframeValue[]); + const [geneNames, setGeneNames] = useState([]); const [, setStatus] = useState("pending"); const { annoMatrix, userDefinedGenes, userDefinedGenesLoading } = useSelector( (state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenes: (state as any).controls.userDefinedGenes, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenesLoading: (state as any).controls.userDefinedGenesLoading, - }) + annoMatrix: state.annoMatrix, + userDefinedGenes: state.controls.userDefinedGenes, + userDefinedGenesLoading: state.controls.userDefinedGenesLoading, + }) ); const prevProps = usePrevious({ annoMatrix }); - // @ts-expect-error ts-migrate(2345) FIXME: Argument of type '() => Promise' is not assi... Remove this comment to see the full error message useEffect(async () => { if (!annoMatrix) return; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - if (annoMatrix !== (prevProps as any)?.annoMatrix) { + if (annoMatrix !== prevProps?.annoMatrix) { const { schema } = annoMatrix; const varIndex = schema.annotations.var.index; setStatus("pending"); try { - const df: Dataframe = await annoMatrix.fetch("var", varIndex); + const df = await annoMatrix.fetch("var", varIndex); setStatus("success"); - setGeneNames(df.col(varIndex).asArray() as DataframeValue[]); + setGeneNames(df.col(varIndex).asArray()); } catch (error) { setStatus("error"); throw error; @@ -63,12 +55,7 @@ function QuickGene() { const handleExpand = () => setIsExpanded(!isExpanded); - const renderGene = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - fuzzySortResult: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - { handleClick, modifiers }: any - ) => { + const renderGene = (fuzzySortResult, { handleClick, modifiers }) => { if (!modifiers.matchesPredicate) { return null; } @@ -81,8 +68,8 @@ function QuickGene() { disabled={modifiers.disabled} data-testid={`suggest-menu-item-${geneName}`} key={geneName} - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - onClick={(g: any /* this fires when user clicks a menu item */) => + onClick={(g) => + /* this fires when user clicks a menu item */ handleClick(g) } text={geneName} @@ -90,8 +77,7 @@ function QuickGene() { ); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const handleClick = (g: any) => { + const handleClick = (g) => { if (!g) return; const gene = g.target; if (userDefinedGenes.indexOf(gene) !== -1) { @@ -105,39 +91,30 @@ function QuickGene() { } }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const filterGenes = (query: any, genes: any) => + const filterGenes = (query, genes) => /* fires on load, once, and then for each character typed into the input */ fuzzysort.go(query, genes, { limit: 5, threshold: -10000, // don't return bad results }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const removeGene = (gene: any) => () => { + const removeGene = (gene) => () => { dispatch({ type: "clear user defined gene", data: gene }); }; - const QuickGenes = useMemo( - () => - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenes.map((gene: any) => ( + const QuickGenes = useMemo(() => userDefinedGenes.map((gene) => ( - )), - [userDefinedGenes] - ); + )), [userDefinedGenes]); return (

} inputProps={{ - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ "data-testid": string; placeholder: string... Remove this comment to see the full error message "data-testid": "gene-search", placeholder: "Quick Gene Search", leftIcon: IconNames.SEARCH, fill: true, }} inputValueRenderer={() => ""} - // @ts-expect-error ts-migrate(2322) FIXME: Type '(query: any, genes: any) => Fuzzysort.Result... Remove this comment to see the full error message itemListPredicate={filterGenes} itemRenderer={renderGene} items={geneNames || ["No genes"]} diff --git a/client/src/components/graph/drawPointsRegl.ts b/client/src/components/graph/drawPointsRegl.js similarity index 89% rename from client/src/components/graph/drawPointsRegl.ts rename to client/src/components/graph/drawPointsRegl.js index ad75e211..01ecc99f 100644 --- a/client/src/components/graph/drawPointsRegl.ts +++ b/client/src/components/graph/drawPointsRegl.js @@ -1,7 +1,6 @@ import { glPointFlags, glPointSize } from "../../util/glHelpers"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export default function drawPointsRegl(regl: any) { +export default function drawPointsRegl(regl) { return regl({ vert: ` precision mediump float; diff --git a/client/src/components/graph/graph.tsx b/client/src/components/graph/graph.js similarity index 51% rename from client/src/components/graph/graph.tsx rename to client/src/components/graph/graph.js index 977d62cb..5b16003d 100644 --- a/client/src/components/graph/graph.tsx +++ b/client/src/components/graph/graph.js @@ -26,7 +26,6 @@ import { flagSelected, flagHighlight, } from "../../util/glHelpers"; -import { Dataframe } from "../../util/dataframe"; /* Simple 2D transforms control all point painting. There are three: @@ -35,8 +34,7 @@ Simple 2D transforms control all point painting. There are three: * camera - apply a 2D camera transformation (pan, zoom) * projection - apply any transformation required for screen size and layout */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function createProjectionTF(viewportWidth: any, viewportHeight: any) { +function createProjectionTF(viewportWidth, viewportHeight) { /* the projection transform accounts for the screen size & other layout */ @@ -55,7 +53,6 @@ function createProjectionTF(viewportWidth: any, viewportHeight: any) { 0, (bottomGutterSizePx - topGutterSizePx) / viewportHeight / aspectScale[1], ]); - // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message mat3.scale(m, m, aspectScale); return m; } @@ -70,48 +67,32 @@ function createModelTF() { return m; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type GraphState = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - crossfilter: (state as any).obsCrossfilter, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - selectionTool: (state as any).graphSelection.tool, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - currentSelection: (state as any).graphSelection.selection, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: (state as any).layoutChoice, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - graphInteractionMode: (state as any).controls.graphInteractionMode, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colors: (state as any).colors, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - pointDilation: (state as any).pointDilation, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, + annoMatrix: state.annoMatrix, + crossfilter: state.obsCrossfilter, + selectionTool: state.graphSelection.tool, + currentSelection: state.graphSelection.selection, + layoutChoice: state.layoutChoice, + graphInteractionMode: state.controls.graphInteractionMode, + colors: state.colors, + pointDilation: state.pointDilation, + genesets: state.genesets.genesets, })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Graph extends React.Component<{}, GraphState> { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static createReglState(canvas: any) { +class Graph extends React.Component { + static createReglState(canvas) { /* - Must be created for each canvas - */ + Must be created for each canvas + */ // setup canvas, webgl draw function and camera const camera = _camera(canvas); const regl = _regl(canvas); const drawPoints = _drawPoints(regl); + // preallocate webgl buffers - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const pointBuffer = regl.buffer(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const colorBuffer = regl.buffer(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const flagBuffer = regl.buffer(); + return { camera, regl, @@ -122,21 +103,14 @@ class Graph extends React.Component<{}, GraphState> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static watchAsync(props: any, prevProps: any) { + static watchAsync(props, prevProps) { return !shallowEqual(props.watchProps, prevProps.watchProps); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - cachedAsyncProps: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - reglCanvas: any; - computePointPositions = memoize((X, Y, modelTF) => { /* - compute the model coordinate for each point - */ + compute the model coordinate for each point + */ const positions = new Float32Array(2 * X.length); for (let i = 0, len = X.length; i < len; i += 1) { const p = vec2.fromValues(X[i], Y[i]); @@ -149,8 +123,8 @@ class Graph extends React.Component<{}, GraphState> { computePointColors = memoize((rgb) => { /* - compute webgl colors for each point - */ + compute webgl colors for each point + */ const colors = new Float32Array(3 * rgb.length); for (let i = 0, len = rgb.length; i < len; i += 1) { colors.set(rgb[i], 3 * i); @@ -199,20 +173,21 @@ class Graph extends React.Component<{}, GraphState> { computePointFlags = memoize( (crossfilter, colorByData, pointDilationData, pointDilationLabel) => { /* - We communicate with the shader using three flags: - - isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor - - isSelected -- the value is selected - - isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting) - - Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda" - like bitmasks. - - We also have separate code paths for generating flags for categorical and - continuous metadata, as they rely on different tests, and some of the flags - (eg, isNaN) are meaningless in the face of categorical metadata. - */ + We communicate with the shader using three flags: + - isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor + - isSelected -- the value is selected + - isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting) + + Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda" + like bitmasks. + + We also have separate code paths for generating flags for categorical and + continuous metadata, as they rely on different tests, and some of the flags + (eg, isNaN) are meaningless in the face of categorical metadata. + */ const nObs = crossfilter.size(); const flags = new Float32Array(nObs); + const selectedFlags = this.computeSelectedFlags( crossfilter, flagSelected, @@ -224,15 +199,16 @@ class Graph extends React.Component<{}, GraphState> { pointDilationLabel ); const colorByFlags = this.computeColorByFlags(nObs, colorByData); + for (let i = 0; i < nObs; i += 1) { flags[i] = selectedFlags[i] + highlightFlags[i] + colorByFlags[i]; } + return flags; } ); - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + constructor(props) { super(props); const viewport = this.getViewportDimensions(); this.reglCanvas = null; @@ -243,18 +219,20 @@ class Graph extends React.Component<{}, GraphState> { tool: null, container: null, viewport, + // projection camera: null, modelTF, - // @ts-expect-error ts-migrate(2345) FIXME: Argument of type '[]' is not assignable to paramet... Remove this comment to see the full error message modelInvTF: mat3.invert([], modelTF), projectionTF: createProjectionTF(viewport.width, viewport.height), + // regl state regl: null, drawPoints: null, pointBuffer: null, colorBuffer: null, flagBuffer: null, + // component rendering derived state - these must stay synchronized // with the reducer state they were generated from. layoutState: { @@ -273,32 +251,23 @@ class Graph extends React.Component<{}, GraphState> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount() { window.addEventListener("resize", this.handleResize); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - componentDidUpdate(prevProps: {}, prevState: GraphState) { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message - selectionTool, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type 'R... Remove this comment to see the full error message - currentSelection, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on type 'R... Remove this comment to see the full error message - graphInteractionMode, - } = this.props; + componentDidUpdate(prevProps, prevState) { + const { selectionTool, currentSelection, graphInteractionMode } = + this.props; const { toolSVG, viewport } = this.state; const hasResized = prevState.viewport.height !== viewport.height || prevState.viewport.width !== viewport.width; let stateChanges = {}; + if ( (viewport.height && viewport.width && !toolSVG) || // first time init hasResized || // window size has changed we want to recreate all SVGs - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type '{... Remove this comment to see the full error message selectionTool !== prevProps.selectionTool || // change of selection tool - // @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message prevProps.graphInteractionMode !== graphInteractionMode // lasso/zoom mode is switched ) { stateChanges = { @@ -306,23 +275,19 @@ class Graph extends React.Component<{}, GraphState> { ...this.createToolSVG(), }; } + /* - if the selection tool or state has changed, ensure that the selection - tool correctly reflects the underlying selection. - */ + if the selection tool or state has changed, ensure that the selection + tool correctly reflects the underlying selection. + */ if ( - // @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message currentSelection !== prevProps.currentSelection || - // @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message graphInteractionMode !== prevProps.graphInteractionMode || - // @ts-expect-error ts-migrate(2339) FIXME: Property 'toolSVG' does not exist on type '{}'. stateChanges.toolSVG ) { const { tool, container } = this.state; this.selectionToolUpdate( - // @ts-expect-error ts-migrate(2339) FIXME: Property 'tool' does not exist on type '{}'. stateChanges.tool ? stateChanges.tool : tool, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'container' does not exist on type '{}'. stateChanges.container ? stateChanges.container : container ); } @@ -332,12 +297,10 @@ class Graph extends React.Component<{}, GraphState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentWillUnmount() { window.removeEventListener("resize", this.handleResize); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleResize = () => { const { state } = this.state; const viewport = this.getViewportDimensions(); @@ -349,35 +312,27 @@ class Graph extends React.Component<{}, GraphState> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleCanvasEvent = (e: any) => { + handleCanvasEvent = (e) => { const { camera, projectionTF } = this.state; if (e.type !== "wheel") e.preventDefault(); if (camera.handleEvent(e, projectionTF)) { this.renderCanvas(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - this.setState((state: any) => ({ - ...state, - updateOverlay: !state.updateOverlay, - })); + this.setState((state) => ({ ...state, updateOverlay: !state.updateOverlay })); } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleBrushDragAction() { /* - event describing brush position: - @-------| - | | - | | - |-------@ - */ + event describing brush position: + @-------| + | | + | | + |-------@ + */ // ignore programatically generated events - // @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message if (d3.event.sourceEvent === null || !d3.event.selection) return; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + const { dispatch, layoutChoice } = this.props; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message const s = d3.event.selection; const northwest = this.mapScreenToPoint(s[0]); const southeast = this.mapScreenToPoint(s[1]); @@ -395,28 +350,23 @@ class Graph extends React.Component<{}, GraphState> { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleBrushStartAction() { // Ignore programatically generated events. - // @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message if (!d3.event.sourceEvent) return; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + const { dispatch } = this.props; dispatch(actions.graphBrushStartAction()); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleBrushEndAction() { // Ignore programatically generated events. - // @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message if (!d3.event.sourceEvent) return; + /* - coordinates will be included if selection made, null - if selection cleared. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + coordinates will be included if selection made, null + if selection cleared. + */ const { dispatch, layoutChoice } = this.props; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message const s = d3.event.selection; if (s) { const northwest = this.mapScreenToPoint(s[0]); @@ -438,27 +388,21 @@ class Graph extends React.Component<{}, GraphState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleBrushDeselectAction() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, layoutChoice } = this.props; dispatch(actions.graphBrushDeselectAction(layoutChoice.current)); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleLassoStart() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, layoutChoice } = this.props; - // @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. dispatch(actions.graphLassoStartAction(layoutChoice.current)); } // when a lasso is completed, filter to the points within the lasso polygon - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleLassoEnd(polygon: any) { + handleLassoEnd(polygon) { const minimumPolygonArea = 10; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, layoutChoice } = this.props; + if ( polygon.length < 3 || Math.abs(d3.polygonArea(polygon)) < minimumPolygonArea @@ -469,38 +413,29 @@ class Graph extends React.Component<{}, GraphState> { dispatch( actions.graphLassoEndAction( layoutChoice.current, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - polygon.map((xy: any) => this.mapScreenToPoint(xy)) + polygon.map((xy) => this.mapScreenToPoint(xy)) ) ); } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleLassoCancel() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, layoutChoice } = this.props; dispatch(actions.graphLassoCancelAction(layoutChoice.current)); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleLassoDeselectAction() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, layoutChoice } = this.props; dispatch(actions.graphLassoDeselectAction(layoutChoice.current)); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleDeselectAction() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message const { selectionTool } = this.props; if (selectionTool === "brush") this.handleBrushDeselectAction(); if (selectionTool === "lasso") this.handleLassoDeselectAction(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleOpacityRangeChange(e: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message + handleOpacityRangeChange(e) { const { dispatch } = this.props; dispatch({ type: "change opacity deselected cells in 2d graph background", @@ -508,17 +443,14 @@ class Graph extends React.Component<{}, GraphState> { }); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - setReglCanvas = (canvas: any) => { + setReglCanvas = (canvas) => { this.reglCanvas = canvas; this.setState({ ...Graph.createReglState(canvas), }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. getViewportDimensions = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'viewportRef' does not exist on type 'Rea... Remove this comment to see the full error message const { viewportRef } = this.props; return { height: viewportRef.clientHeight, @@ -526,19 +458,19 @@ class Graph extends React.Component<{}, GraphState> { }; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. createToolSVG = () => { /* - Called from componentDidUpdate. Create the tool SVG, and return any - state changes that should be passed to setState(). - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message + Called from componentDidUpdate. Create the tool SVG, and return any + state changes that should be passed to setState(). + */ const { selectionTool, graphInteractionMode } = this.props; const { viewport } = this.state; + /* clear out whatever was on the div, even if nothing, but usually the brushes etc */ const lasso = d3.select("#lasso-layer"); if (lasso.empty()) return {}; // still initializing lasso.selectAll(".lasso-group").remove(); + // Don't render or recreate toolSVG if currently in zoom mode if (graphInteractionMode !== "select") { // don't return "change" of state unless we are really changing it! @@ -546,6 +478,7 @@ class Graph extends React.Component<{}, GraphState> { if (toolSVG === undefined) return {}; return { toolSVG: undefined }; } + let handleStart; let handleDrag; let handleEnd; @@ -559,6 +492,7 @@ class Graph extends React.Component<{}, GraphState> { handleEnd = this.handleLassoEnd.bind(this); handleCancel = this.handleLassoCancel.bind(this); } + const { svg: newToolSVG, tool, @@ -571,11 +505,11 @@ class Graph extends React.Component<{}, GraphState> { handleCancel, viewport ); + return { toolSVG: newToolSVG, tool, container }; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fetchAsyncProps = async (props: any) => { + fetchAsyncProps = async (props) => { const { annoMatrix, colors: colorsProp, @@ -585,19 +519,24 @@ class Graph extends React.Component<{}, GraphState> { viewport, } = props.watchProps; const { modelTF } = this.state; + const [layoutDf, colorDf, pointDilationDf] = await this.fetchData( annoMatrix, layoutChoice, colorsProp, pointDilation ); + const { currentDimNames } = layoutChoice; const X = layoutDf.col(currentDimNames[0]).asArray(); const Y = layoutDf.col(currentDimNames[1]).asArray(); const positions = this.computePointPositions(X, Y, modelTF); + const colorTable = this.updateColorTable(colorsProp, colorDf); const colors = this.computePointColors(colorTable.rgb); - const colorByData = colorDf?.icol(0)?.asArray(); + + const { colorAccessor } = colorsProp; + const colorByData = colorDf?.col(colorAccessor)?.asArray(); const { metadataField: pointDilationCategory, categoryField: pointDilationLabel, @@ -611,6 +550,7 @@ class Graph extends React.Component<{}, GraphState> { pointDilationData, pointDilationLabel ); + const { width, height } = viewport; return { positions, @@ -621,53 +561,50 @@ class Graph extends React.Component<{}, GraphState> { }; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - async fetchData( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - annoMatrix: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - layoutChoice: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colors: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - pointDilation: any - ): Promise<[Dataframe, Dataframe | null, Dataframe | null]> { + async fetchData(annoMatrix, layoutChoice, colors, pointDilation) { /* - fetch all data needed. Includes: - - the color by dataframe - - the layout dataframe - - the point dilation dataframe - */ + fetch all data needed. Includes: + - the color by dataframe + - the layout dataframe + - the point dilation dataframe + */ const { metadataField: pointDilationAccessor } = pointDilation; + + const promises = []; + // layout + promises.push(annoMatrix.fetch("emb", layoutChoice.current)); + + // color const query = this.createColorByQuery(colors); - const promises: [ - Promise, - Promise, - Promise - ] = [ - annoMatrix.fetch("emb", layoutChoice.current), - query ? annoMatrix.fetch(...query) : Promise.resolve(null), - pointDilationAccessor - ? annoMatrix.fetch("obs", pointDilationAccessor) - : Promise.resolve(null), - ]; + if (query) { + promises.push(annoMatrix.fetch(...query)); + } else { + promises.push(Promise.resolve(null)); + } + + // point highlighting + if (pointDilationAccessor) { + promises.push(annoMatrix.fetch("obs", pointDilationAccessor)); + } else { + promises.push(Promise.resolve(null)); + } + return Promise.all(promises); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - brushToolUpdate(tool: any, container: any) { + brushToolUpdate(tool, container) { /* - this is called from componentDidUpdate(), so be very careful using - anything from this.state, which may be updated asynchronously. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message + this is called from componentDidUpdate(), so be very careful using + anything from this.state, which may be updated asynchronously. + */ const { currentSelection } = this.props; if (container) { const toolCurrentSelection = d3.brushSelection(container.node()); + if (currentSelection.mode === "within-rect") { /* - if there is a selection, make sure the brush tool matches - */ + if there is a selection, make sure the brush tool matches + */ const screenCoords = [ this.mapPointToScreen(currentSelection.brushCoords.northwest), this.mapPointToScreen(currentSelection.brushCoords.southeast), @@ -682,7 +619,6 @@ class Graph extends React.Component<{}, GraphState> { for (let x = 0; x < 2; x += 1) { for (let y = 0; y < 2; y += 1) { delta += Math.abs( - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message screenCoords[x][y] - toolCurrentSelection[x][y] ); } @@ -698,20 +634,17 @@ class Graph extends React.Component<{}, GraphState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - lassoToolUpdate(tool: any) { + lassoToolUpdate(tool) { /* - this is called from componentDidUpdate(), so be very careful using - anything from this.state, which may be updated asynchronously. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message + this is called from componentDidUpdate(), so be very careful using + anything from this.state, which may be updated asynchronously. + */ const { currentSelection } = this.props; if (currentSelection.mode === "within-polygon") { /* - if there is a current selection, make sure the lasso tool matches - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const polygon = currentSelection.polygon.map((p: any) => + if there is a current selection, make sure the lasso tool matches + */ + const polygon = currentSelection.polygon.map((p) => this.mapPointToScreen(p) ); tool.move(polygon); @@ -720,20 +653,17 @@ class Graph extends React.Component<{}, GraphState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectionToolUpdate(tool: any, container: any) { + selectionToolUpdate(tool, container) { /* - this is called from componentDidUpdate(), so be very careful using - anything from this.state, which may be updated asynchronously. - */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message + this is called from componentDidUpdate(), so be very careful using + anything from this.state, which may be updated asynchronously. + */ const { selectionTool } = this.props; switch (selectionTool) { case "brush": this.brushToolUpdate(tool, container); break; case "lasso": - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2. this.lassoToolUpdate(tool, container); break; default: @@ -742,17 +672,19 @@ class Graph extends React.Component<{}, GraphState> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - mapScreenToPoint(pin: any) { + mapScreenToPoint(pin) { /* - Map an XY coordinates from screen domain to cell/point range, - accounting for current pan/zoom camera. - */ + Map an XY coordinates from screen domain to cell/point range, + accounting for current pan/zoom camera. + */ + const { camera, projectionTF, modelInvTF, viewport } = this.state; const cameraInvTF = camera.invView(); + /* screen -> gl */ const x = (2 * pin[0]) / viewport.width - 1; const y = 2 * (1 - pin[1] / viewport.height) - 1; + const xy = vec2.fromValues(x, y); const projectionInvTF = mat3.invert(mat3.create(), projectionTF); vec2.transformMat3(xy, xy, projectionInvTF); @@ -761,17 +693,19 @@ class Graph extends React.Component<{}, GraphState> { return xy; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - mapPointToScreen(xyCell: any) { + mapPointToScreen(xyCell) { /* - Map an XY coordinate from cell/point domain to screen range. Inverse - of mapScreenToPoint() - */ + Map an XY coordinate from cell/point domain to screen range. Inverse + of mapScreenToPoint() + */ + const { camera, projectionTF, modelTF, viewport } = this.state; const cameraTF = camera.view(); + const xy = vec2.transformMat3(vec2.create(), xyCell, modelTF); vec2.transformMat3(xy, xy, cameraTF); vec2.transformMat3(xy, xy, projectionTF); + return [ Math.round(((xy[0] + 1) * viewport.width) / 2), Math.round(-((xy[1] + 1) / 2 - 1) * viewport.height), @@ -799,12 +733,12 @@ class Graph extends React.Component<{}, GraphState> { ); }); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - updateReglAndRender(asyncProps: any, prevAsyncProps: any) { + updateReglAndRender(asyncProps, prevAsyncProps) { const { positions, colors, flags, height, width } = asyncProps; this.cachedAsyncProps = asyncProps; const { pointBuffer, colorBuffer, flagBuffer } = this.state; let needToRenderCanvas = false; + if (height !== prevAsyncProps?.height || width !== prevAsyncProps?.width) { needToRenderCanvas = true; } @@ -823,11 +757,10 @@ class Graph extends React.Component<{}, GraphState> { if (needToRenderCanvas) this.renderCanvas(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - updateColorTable(colors: any, colorDf: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + updateColorTable(colors, colorDf) { const { annoMatrix } = this.props; const { schema } = annoMatrix; + /* update color table state */ if (!colors || !colorDf) { return createColorTable( @@ -838,6 +771,7 @@ class Graph extends React.Component<{}, GraphState> { null ); } + const { colorAccessor, userColors, colorMode } = colors; return createColorTable( colorMode, @@ -848,35 +782,26 @@ class Graph extends React.Component<{}, GraphState> { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - createColorByQuery(colors: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + createColorByQuery(colors) { const { annoMatrix, genesets } = this.props; const { schema } = annoMatrix; const { colorMode, colorAccessor } = colors; + return createColorQuery(colorMode, colorAccessor, schema, genesets); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderPoints( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - regl: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - drawPoints: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - pointBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - flagBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - camera: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - projectionTF: any + regl, + drawPoints, + colorBuffer, + pointBuffer, + flagBuffer, + camera, + projectionTF ) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message const { annoMatrix } = this.props; if (!this.reglCanvas || !annoMatrix) return; + const { schema } = annoMatrix; const cameraTF = camera.view(); const projView = mat3.multiply(mat3.create(), projectionTF, cameraTF); @@ -899,24 +824,18 @@ class Graph extends React.Component<{}, GraphState> { regl._gl.flush(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message graphInteractionMode, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on ... Remove this comment to see the full error message annoMatrix, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on ... Remove this comment to see the full error message colors, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on ... Remove this comment to see the full error message layoutChoice, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on ... Remove this comment to see the full error message pointDilation, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on ... Remove this comment to see the full error message crossfilter, } = this.props; const { modelTF, projectionTF, camera, viewport, regl } = this.state; const cameraTF = camera?.view()?.slice(); + return (
{ }} > { }} > - {/* eslint-disable-next-line @typescript-eslint/no-use-before-define --- StillLoading used before defined */} { {(error) => ( - // eslint-disable-next-line @typescript-eslint/no-use-before-define --- ErrorLoading used before defined { } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const ErrorLoading = ({ displayName, error, width, height }: any) => { +const ErrorLoading = ({ displayName, error, width, height }) => { console.log(error); // log to console as this is an unepected error return (
{ ); }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const StillLoading = ({ displayName, width, height }: any) => ( +const StillLoading = ({ displayName, width, height }) => /* Render a busy/loading indicator */ -
+ (
-
-
-); + ) +; + export default Graph; diff --git a/client/src/components/graph/overlays/centroidLabels.js b/client/src/components/graph/overlays/centroidLabels.js new file mode 100644 index 00000000..3f4d19aa --- /dev/null +++ b/client/src/components/graph/overlays/centroidLabels.js @@ -0,0 +1,218 @@ +import React, { PureComponent } from "react"; +import { connect, shallowEqual } from "react-redux"; +import Async from "react-async"; + +import { categoryLabelDisplayStringLongLength } from "../../../globals"; +import calcCentroid from "../../../util/centroid"; +import { createColorQuery } from "../../../util/stateManager/colorHelpers"; + +export default +@connect((state) => ({ + annoMatrix: state.annoMatrix, + colors: state.colors, + layoutChoice: state.layoutChoice, + dilatedValue: state.pointDilation.categoryField, + categoricalSelection: state.categoricalSelection, + showLabels: state.centroidLabels?.showLabels, + genesets: state.genesets.genesets, +})) +class CentroidLabels extends PureComponent { + static watchAsync(props, prevProps) { + return !shallowEqual(props.watchProps, prevProps.watchProps); + } + + fetchAsyncProps = async (props) => { + const { + annoMatrix, + colors, + layoutChoice, + categoricalSelection, + showLabels, + } = props.watchProps; + const { schema } = annoMatrix; + const { colorAccessor } = colors; + + const [layoutDf, colorDf] = await this.fetchData(); + let labels; + if (colorDf) { + labels = calcCentroid( + schema, + colorAccessor, + colorDf, + layoutChoice, + layoutDf + ); + } else { + labels = new Map(); + } + + const { overlaySetShowing } = this.props; + overlaySetShowing("centroidLabels", showLabels && labels.size > 0); + + return { + labels, + colorAccessor, + category: categoricalSelection[colorAccessor], + }; + }; + + handleMouseEnter = (e, colorAccessor, label) => { + const { dispatch } = this.props; + dispatch({ + type: "category value mouse hover start", + metadataField: colorAccessor, + categoryField: label, + }); + }; + + handleMouseOut = (e, colorAccessor, label) => { + const { dispatch } = this.props; + dispatch({ + type: "category value mouse hover end", + metadataField: colorAccessor, + categoryField: label, + }); + }; + + colorByQuery() { + const { annoMatrix, colors, genesets } = this.props; + const { schema } = annoMatrix; + const { colorMode, colorAccessor } = colors; + return createColorQuery(colorMode, colorAccessor, schema, genesets); + } + + async fetchData() { + const { annoMatrix, layoutChoice } = this.props; + // fetch all data we need: layout, category + const promises = []; + // layout + promises.push(annoMatrix.fetch("emb", layoutChoice.current)); + // category to label - we ONLY label on obs, never on X, etc. + const query = this.colorByQuery(); + if (query && query[0] === "obs") { + promises.push(annoMatrix.fetch(...query)); + } else { + promises.push(Promise.resolve(null)); + } + + return Promise.all(promises); + } + + render() { + const { + inverseTransform, + dilatedValue, + categoricalSelection, + showLabels, + colors, + annoMatrix, + layoutChoice, + } = this.props; + + return ( + + + {(asyncProps) => { + if (!showLabels) return null; + + const labelSVGS = []; + const deselectOpacity = 0.375; + const { category, colorAccessor, labels } = asyncProps; + + labels.forEach((coords, label) => { + const selected = category.get(label) ?? true; + + // Mirror LSB middle truncation + let displayLabel = label; + if (displayLabel.length > categoryLabelDisplayStringLongLength) { + displayLabel = `${label.slice( + 0, + categoryLabelDisplayStringLongLength / 2 + )}…${label.slice(-categoryLabelDisplayStringLongLength / 2)}`; + } + + labelSVGS.push( + // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative + + + ); + } +} + +const Label = ({ + label, + dilatedValue, + coords, + inverseTransform, + opacity, + colorAccessor, + displayLabel, + onMouseEnter, + onMouseOut, +}) => { + /* + Render a label at a given coordinate. + */ + let fontSize = "15px"; + let fontWeight = null; + if (label === dilatedValue) { + fontSize = "18px"; + fontWeight = "800"; + } + + return ( + + {/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/} + onMouseEnter(e, colorAccessor, label)} + onMouseOut={(e) => onMouseOut(e, colorAccessor, label)} + pointerEvents="visiblePainted" + > + {displayLabel} + + + ); +}; diff --git a/client/src/components/graph/overlays/centroidLabels.tsx b/client/src/components/graph/overlays/centroidLabels.tsx deleted file mode 100644 index 0f0da386..00000000 --- a/client/src/components/graph/overlays/centroidLabels.tsx +++ /dev/null @@ -1,241 +0,0 @@ -import React, { PureComponent } from "react"; -import { connect, shallowEqual } from "react-redux"; -import Async from "react-async"; - -import { categoryLabelDisplayStringLongLength } from "../../../globals"; -import calcCentroid from "../../../util/centroid"; -import { createColorQuery } from "../../../util/stateManager/colorHelpers"; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colors: (state as any).colors, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: (state as any).layoutChoice, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dilatedValue: (state as any).pointDilation.categoryField, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoricalSelection: (state as any).categoricalSelection, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - showLabels: (state as any).centroidLabels?.showLabels, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, -})) -export default class CentroidLabels extends PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static watchAsync(props: any, prevProps: any) { - return !shallowEqual(props.watchProps, prevProps.watchProps); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fetchAsyncProps = async (props: any) => { - const { - annoMatrix, - colors, - layoutChoice, - categoricalSelection, - showLabels, - } = props.watchProps; - const { schema } = annoMatrix; - const { colorAccessor } = colors; - const [layoutDf, colorDf] = await this.fetchData(); - let labels; - if (colorDf) { - labels = calcCentroid( - schema, - colorAccessor, - colorDf, - layoutChoice, - layoutDf - ); - } else { - labels = new Map(); - } - // @ts-expect-error ts-migrate(2339) FIXME: Property 'overlaySetShowing' does not exist on typ... Remove this comment to see the full error message - const { overlaySetShowing } = this.props; - overlaySetShowing("centroidLabels", showLabels && labels.size > 0); - return { - labels, - colorAccessor, - category: categoricalSelection[colorAccessor], - }; - }; - - // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read. - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleMouseEnter = (e: any, colorAccessor: any, label: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch({ - type: "category value mouse hover start", - metadataField: colorAccessor, - categoryField: label, - }); - }; - - // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read. - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleMouseOut = (e: any, colorAccessor: any, label: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch({ - type: "category value mouse hover end", - metadataField: colorAccessor, - categoryField: label, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - colorByQuery() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message - const { annoMatrix, colors, genesets } = this.props; - const { schema } = annoMatrix; - const { colorMode, colorAccessor } = colors; - return createColorQuery(colorMode, colorAccessor, schema, genesets); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - async fetchData() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message - const { annoMatrix, layoutChoice } = this.props; - // fetch all data we need: layout, category - const promises = []; - // layout - promises.push(annoMatrix.fetch("emb", layoutChoice.current)); - // category to label - we ONLY label on obs, never on X, etc. - const query = this.colorByQuery(); - if (query && query[0] === "obs") { - promises.push(annoMatrix.fetch(...query)); - } else { - promises.push(Promise.resolve(null)); - } - return Promise.all(promises); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'inverseTransform' does not exist on type... Remove this comment to see the full error message - inverseTransform, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dilatedValue' does not exist on type 'Re... Remove this comment to see the full error message - dilatedValue, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message - categoricalSelection, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'showLabels' does not exist on type 'Read... Remove this comment to see the full error message - showLabels, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message - colors, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message - annoMatrix, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on type 'Re... Remove this comment to see the full error message - layoutChoice, - } = this.props; - return ( - - - {(asyncProps) => { - if (!showLabels) return null; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const labelSVGS: any = []; - const deselectOpacity = 0.375; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'category' does not exist on type 'unknow... Remove this comment to see the full error message - const { category, colorAccessor, labels } = asyncProps; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - labels.forEach((coords: any, label: any) => { - const selected = category.get(label) ?? true; - // Mirror LSB middle truncation - let displayLabel = label; - if (displayLabel.length > categoryLabelDisplayStringLongLength) { - displayLabel = `${label.slice( - 0, - categoryLabelDisplayStringLongLength / 2 - )}…${label.slice(-categoryLabelDisplayStringLongLength / 2)}`; - } - labelSVGS.push( - // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative - - - ); - } -} - -const Label = ({ - label, - dilatedValue, - coords, - inverseTransform, - opacity, - colorAccessor, - displayLabel, - onMouseEnter, - onMouseOut, // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -}: any) => { - /* - Render a label at a given coordinate. - */ - let fontSize = "15px"; - let fontWeight = null; - if (label === dilatedValue) { - fontSize = "18px"; - fontWeight = "800"; - } - - return ( - - {/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/} - onMouseEnter(e, colorAccessor, label)} - onMouseOut={(e) => onMouseOut(e, colorAccessor, label)} - pointerEvents="visiblePainted" - > - {displayLabel} - - - ); -}; diff --git a/client/src/components/graph/overlays/graphOverlayLayer.tsx b/client/src/components/graph/overlays/graphOverlayLayer.js similarity index 54% rename from client/src/components/graph/overlays/graphOverlayLayer.tsx rename to client/src/components/graph/overlays/graphOverlayLayer.js index feab192e..0f9ab350 100644 --- a/client/src/components/graph/overlays/graphOverlayLayer.tsx +++ b/client/src/components/graph/overlays/graphOverlayLayer.js @@ -1,29 +1,22 @@ import React, { PureComponent, cloneElement } from "react"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module '../graph.css' or its correspon... Remove this comment to see the full error message import styles from "../graph.css"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -export default class GraphOverlayLayer extends PureComponent<{}, State> { +export default class GraphOverlayLayer extends PureComponent { /* This component takes its children (assumed in the data coordinate space ([0, 1] range, origin in bottom left corner)) and transforms itself multiple times resulting in screen space ([0, screenWidth/Height] range, origin in top left corner) Children are assigned in the graph component and must implement onDisplayChange() */ - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + constructor(props) { super(props); this.state = { display: {}, }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - matrixToTransformString = (m: any) => + matrixToTransformString = (m) => /* Translates the gl-matrix mat3 to SVG matrix transform style @@ -32,37 +25,24 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> { b d f / [a, b, 0, c, d, 0, e, f, 1] => matrix(a, b, c, d, e, f) / matrix(sx, 0, 0, sy, tx, ty) / matrix(m[0] m[3] m[1] m[4] m[6] m[7]) 0 0 1 */ - `matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`; + `matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})` + ; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - reverseMatrixScaleTransformString = (m: any) => - `matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`; + reverseMatrixScaleTransformString = (m) => `matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`; // This is passed to all children, should be called when an overlay's display state is toggled along with the overlay name and its new display state in boolean form - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - overlaySetShowing = (overlay: any, displaying: any) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - this.setState((state: any) => ({ - ...state, - display: { ...state.display, [overlay]: displaying }, - })); + overlaySetShowing = (overlay, displaying) => { + this.setState((state) => ({ ...state, display: { ...state.display, [overlay]: displaying } })); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'cameraTF' does not exist on type 'Readon... Remove this comment to see the full error message cameraTF, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'modelTF' does not exist on type 'Readonl... Remove this comment to see the full error message modelTF, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'projectionTF' does not exist on type 'Re... Remove this comment to see the full error message projectionTF, children, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCanvasEvent' does not exist on typ... Remove this comment to see the full error message handleCanvasEvent, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message width, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message height, } = this.props; const { display } = this.state; @@ -81,7 +61,6 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> { // Copy the children passed with the overlay and add the inverse transform and onDisplayChange props const newChildren = React.Children.map(children, (child) => - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. cloneElement(child, { inverseTransform, overlaySetShowing: this.overlaySetShowing, diff --git a/client/src/components/graph/setupLasso.ts b/client/src/components/graph/setupLasso.js similarity index 59% rename from client/src/components/graph/setupLasso.ts rename to client/src/components/graph/setupLasso.js index afbe3678..095b4ec6 100644 --- a/client/src/components/graph/setupLasso.ts +++ b/client/src/components/graph/setupLasso.js @@ -1,28 +1,19 @@ import * as d3 from "d3"; import { Colors } from "@blueprintjs/core"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Lasso = () => { const dispatch = d3.dispatch("start", "end", "cancel"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const lasso = (svg: any) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let lassoPolygon: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let lassoPath: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let closePath: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - let lassoInProgress: any; + const lasso = (svg) => { + let lassoPolygon; + let lassoPath; + let closePath; + let lassoInProgress; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const polygonToPath = (polygon: any) => - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - `M${polygon.map((d: any) => d.join(",")).join("L")}`; + const polygonToPath = (polygon) => + `M${polygon.map((d) => d.join(",")).join("L")}`; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const distance = (pt1: any, pt2: any) => + const distance = (pt1, pt2) => Math.sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2); // distance last point has to be to first point before it auto closes when mouse is released @@ -30,14 +21,12 @@ const Lasso = () => { const lassoPathColor = Colors.BLUE5; const handleDragStart = () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - lassoPolygon = [(d3 as any).mouse(svg.node())]; // current x y of mouse within element + lassoPolygon = [d3.mouse(svg.node())]; // current x y of mouse within element if (lassoPath) { // If the existing path is in progress if (lassoInProgress) { // cancel the existing lasso - // eslint-disable-next-line @typescript-eslint/no-use-before-define --- handleCancel used before defined handleCancel(); // Don't continue with current drag start return; @@ -48,14 +37,12 @@ const Lasso = () => { // We're starting a new drag lassoInProgress = true; - // eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined lassoPath = g .append("path") .attr("data-testid", "lasso-element") .attr("fill-opacity", 0.1) .attr("stroke-dasharray", "3, 3"); - // eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined closePath = g .append("line") .attr("x2", lassoPolygon[0][0]) @@ -66,8 +53,7 @@ const Lasso = () => { }; const handleDrag = () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const point = (d3 as any).mouse(svg.node()); + const point = d3.mouse(svg.node()); lassoPolygon.push(point); lassoPath.attr("d", polygonToPath(lassoPolygon)); @@ -137,12 +123,12 @@ const Lasso = () => { area.call(drag); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (lasso as any).reset = () => { + lasso.reset = () => { if (lassoPath) { lassoPath.remove(); lassoPath = null; } + lassoPolygon = null; if (closePath) { closePath.remove(); @@ -150,11 +136,10 @@ const Lasso = () => { } }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (lasso as any).move = (polygon: any) => { + lasso.move = (polygon) => { if (polygon !== lassoPolygon || polygon.length !== lassoPolygon.length) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'reset' does not exist on type '(svg: any... Remove this comment to see the full error message lasso.reset(); + lassoPolygon = polygon; lassoPath = g .append("path") @@ -163,13 +148,13 @@ const Lasso = () => { .attr("fill-opacity", 0.1) .attr("stroke", lassoPathColor) .attr("stroke-dasharray", "3, 3"); + lassoPath.attr("d", `${polygonToPath(lassoPolygon)}Z`); } }; }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - lasso.on = (type: any, callback: any) => { + lasso.on = (type, callback) => { dispatch.on(type, callback); return lasso; }; diff --git a/client/src/components/graph/setupSVGandBrush.js b/client/src/components/graph/setupSVGandBrush.js new file mode 100644 index 00000000..bedf96a9 --- /dev/null +++ b/client/src/components/graph/setupSVGandBrush.js @@ -0,0 +1,54 @@ +import * as d3 from "d3"; +import Lasso from "./setupLasso"; + +/****************************************** +******************************************* + put svg & brush in DOM +******************************************* +******************************************/ + +export default ( + selectionToolType, + handleStartAction, + handleDragAction, + handleEndAction, + handleCancelAction, + viewport +) => { + const svg = d3.select("#graph-wrapper").select("#lasso-layer"); + if (svg.empty()) return {}; + + if (selectionToolType === "brush") { + const brush = d3 + .brush() + .extent([ + [0, 0], + [viewport.width, viewport.height], + ]) + .on("start", handleStartAction) + .on("brush", handleDragAction) + // FYI, brush doesn't generate cancel + .on("end", handleEndAction); + + const brushContainer = svg + .append("g") + .attr("class", "graph_brush") + .call(brush); + + return { svg, container: brushContainer, tool: brush }; + } + + if (selectionToolType === "lasso") { + const lasso = Lasso() + .on("end", handleEndAction) + // FYI, Lasso doesn't generate drag + .on("start", handleStartAction) + .on("cancel", handleCancelAction); + + const lassoContainer = svg.call(lasso); + + return { svg, container: lassoContainer, tool: lasso }; + } + + throw new Error("unknown graph selection tool"); +}; diff --git a/client/src/components/graph/setupSVGandBrush.ts b/client/src/components/graph/setupSVGandBrush.ts deleted file mode 100644 index e8071b1e..00000000 --- a/client/src/components/graph/setupSVGandBrush.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as d3 from "d3"; -import Lasso from "./setupLasso"; - -/****************************************** -******************************************* - put svg & brush in DOM -******************************************* -******************************************/ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export default ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectionToolType: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleStartAction: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleDragAction: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleEndAction: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleCancelAction: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - viewport: any -) => { - const svg = d3.select("#graph-wrapper").select("#lasso-layer"); - if (svg.empty()) return {}; - - if (selectionToolType === "brush") { - const brush = d3 - .brush() - .extent([ - [0, 0], - [viewport.width, viewport.height], - ]) - .on("start", handleStartAction) - .on("brush", handleDragAction) - // FYI, brush doesn't generate cancel - .on("end", handleEndAction); - - const brushContainer = svg - .append("g") - .attr("class", "graph_brush") - .call(brush); - - return { svg, container: brushContainer, tool: brush }; - } - - if (selectionToolType === "lasso") { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const lasso = (Lasso() as any) - .on("end", handleEndAction) - // FYI, Lasso doesn't generate drag - .on("start", handleStartAction) - .on("cancel", handleCancelAction); - - const lassoContainer = svg.call(lasso); - - return { svg, container: lassoContainer, tool: lasso }; - } - - throw new Error("unknown graph selection tool"); -}; diff --git a/client/src/components/infoDrawer/infoDrawer.js b/client/src/components/infoDrawer/infoDrawer.js new file mode 100644 index 00000000..527dcd44 --- /dev/null +++ b/client/src/components/infoDrawer/infoDrawer.js @@ -0,0 +1,61 @@ +import React, { PureComponent } from "react"; +import { connect } from "react-redux"; +import { Drawer } from "@blueprintjs/core"; + +import InfoFormat from "./infoFormat"; +import { selectableCategoryNames } from "../../util/stateManager/controlsHelpers"; + +@connect((state) => ({ + schema: state.annoMatrix.schema, + datasetTitle: state.config?.displayNames?.dataset ?? "", + aboutURL: state.config?.links?.["about-dataset"], + isOpen: state.controls.datasetDrawer, + dataPortalProps: state.config?.corpora_props, + })) +class InfoDrawer extends PureComponent { + handleClose = () => { + const { dispatch } = this.props; + + dispatch({ type: "toggle dataset drawer" }); + }; + + render() { + const { + position, + aboutURL, + datasetTitle, + schema, + isOpen, + dataPortalProps, + } = this.props; + + const allCategoryNames = selectableCategoryNames(schema).sort(); + const singleValueCategories = new Map(); + + allCategoryNames.forEach((catName) => { + const isUserAnno = schema?.annotations?.obsByName[catName]?.writable; + const colSchema = schema.annotations.obsByName[catName]; + if (!isUserAnno && colSchema.categories?.length === 1) { + singleValueCategories.set(catName, colSchema.categories[0]); + } + }); + + return ( + + + + ); + } +} +export default InfoDrawer; diff --git a/client/src/components/infoDrawer/infoDrawer.tsx b/client/src/components/infoDrawer/infoDrawer.tsx deleted file mode 100644 index 806f7225..00000000 --- a/client/src/components/infoDrawer/infoDrawer.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { PureComponent } from "react"; -import { connect } from "react-redux"; -import { Drawer } from "@blueprintjs/core"; - -import InfoFormat from "./infoFormat"; -import { selectableCategoryNames } from "../../util/stateManager/controlsHelpers"; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: (state as any).annoMatrix.schema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - datasetTitle: (state as any).config?.displayNames?.dataset ?? "", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - aboutURL: (state as any).config?.links?.["about-dataset"], - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - isOpen: (state as any).controls.datasetDrawer, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dataPortalProps: (state as any).config?.corpora_props, -})) -class InfoDrawer extends PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleClose = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - - dispatch({ type: "toggle dataset drawer" }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'position' does not exist on type 'Readon... Remove this comment to see the full error message - position, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'aboutURL' does not exist on type 'Readon... Remove this comment to see the full error message - aboutURL, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type 'Re... Remove this comment to see the full error message - datasetTitle, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message - schema, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message - isOpen, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dataPortalProps' does not exist on type ... Remove this comment to see the full error message - dataPortalProps, - } = this.props; - - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. - const allCategoryNames = selectableCategoryNames(schema).sort(); - const singleValueCategories = new Map(); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - allCategoryNames.forEach((catName: any) => { - const isUserAnno = schema?.annotations?.obsByName[catName]?.writable; - const colSchema = schema.annotations.obsByName[catName]; - if (!isUserAnno && colSchema.categories?.length === 1) { - singleValueCategories.set(catName, colSchema.categories[0]); - } - }); - - return ( - - - - ); - } -} -export default InfoDrawer; diff --git a/client/src/components/infoDrawer/infoFormat.tsx b/client/src/components/infoDrawer/infoFormat.js similarity index 63% rename from client/src/components/infoDrawer/infoFormat.tsx rename to client/src/components/infoDrawer/infoFormat.js index b1a1d956..ad414bfe 100644 --- a/client/src/components/infoDrawer/infoFormat.tsx +++ b/client/src/components/infoDrawer/infoFormat.js @@ -1,16 +1,14 @@ import { H3, H1, UL, HTMLTable, Classes } from "@blueprintjs/core"; import React from "react"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const renderContributors = (contributors: any, affiliations: any) => { +const renderContributors = (contributors, affiliations) => { // eslint-disable-next-line no-constant-condition -- Temp removed contributor section to avoid publishing PII if (!contributors || contributors.length === 0 || true) return null; return ( <>

Contributors

- {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {contributors.map((contributor: any) => { + {contributors.map((contributor) => { const { email, name, institution } = contributor; return ( @@ -29,8 +27,7 @@ const renderContributors = (contributors: any, affiliations: any) => { // generates a list of unique institutions by order of appearance in contributors const buildAffiliations = (contributors = []) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const affiliations: any = []; + const affiliations = []; contributors.forEach((contributor) => { const { institution } = contributor; if (affiliations.indexOf(institution) === -1) { @@ -40,15 +37,13 @@ const buildAffiliations = (contributors = []) => { return affiliations; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const renderAffiliations = (affiliations: any) => { +const renderAffiliations = (affiliations) => { if (affiliations.length === 0) return null; return ( <>

Affiliations

    - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {affiliations.map((item: any, index: any) => ( + {affiliations.map((item, index) => (
    {index + 1} {" "} @@ -60,8 +55,7 @@ const renderAffiliations = (affiliations: any) => { ); }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const renderDOILink = (type: any, doi: any) => { +const renderDOILink = (type, doi) => { if (!doi) return null; return ( <> @@ -77,12 +71,7 @@ const renderDOILink = (type: any, doi: any) => { const ONTOLOGY_KEY = "ontology_term_id"; // Render list of metadata attributes found in categorical field -const renderDatasetMetadata = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - singleValueCategories: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - corporaMetadata: any -) => { +const renderDatasetMetadata = (singleValueCategories, corporaMetadata) => { if (singleValueCategories.size === 0) return null; return ( <> @@ -101,34 +90,29 @@ const renderDatasetMetadata = ( {Object.entries(corporaMetadata).map(([key, value]) => ( - - {`${key}:`} - {/* @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'ReactNod... Remove this comment to see the full error message */} - {value} - - - ))} + + {`${key}:`} + {value} + + + ))} {Array.from(singleValueCategories).reduce((elems, pair) => { - // @ts-expect-error ts-migrate(2488) FIXME: Type 'unknown' must have a '[Symbol.iterator]()' m... Remove this comment to see the full error message const [category, value] = pair; // If the value is empty skip it if (!value) return elems; // If this category is a ontology term, let's add its value to the previous node if (String(category).includes(ONTOLOGY_KEY)) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const prevElem = (elems as any).pop(); + const prevElem = elems.pop(); const newChildren = [...prevElem.props.children]; newChildren.splice(2, 1, [{value}]); // Props aren't extensible so we must clone and alter the component to append the new child - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (elems as any).push( + elems.push( React.cloneElement(prevElem, prevElem.props, newChildren) ); } else { // Create the list item - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (elems as any).push( + elems.push( {`${category}:`} {value} @@ -146,16 +130,14 @@ const renderDatasetMetadata = ( // Renders any links found in the config where link_type is not "SUMMARY" // If there are no links in the config, render the aboutURL -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -const renderLinks = (projectLinks: any, aboutURL: any) => { +const renderLinks = (projectLinks, aboutURL) => { if (!projectLinks && !aboutURL) return null; if (projectLinks) return ( <>

    Project Links

      - {/* eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. */} - {projectLinks.map((link: any) => { + {projectLinks.map((link) => { if (link.link_type === "SUMMARY") return null; return (
    • @@ -182,7 +164,6 @@ const renderLinks = (projectLinks: any, aboutURL: any) => { }; const InfoFormat = React.memo( - // @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type '{ ... Remove this comment to see the full error message ({ datasetTitle, singleValueCategories, aboutURL, dataPortalProps = {} }) => { if ( ["1.0.0", "1.1.0"].indexOf( diff --git a/client/src/components/labelInput.tsx b/client/src/components/labelInput.js similarity index 50% rename from client/src/components/labelInput.tsx rename to client/src/components/labelInput.js index d6b5e766..be460a6d 100644 --- a/client/src/components/labelInput.tsx +++ b/client/src/components/labelInput.js @@ -3,11 +3,7 @@ import { InputGroup, MenuItem, Keys } from "@blueprintjs/core"; import { Suggest } from "@blueprintjs/select"; import fuzzysort from "fuzzysort"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -export default class LabelInput extends React.PureComponent<{}, State> { +export default class LabelInput extends React.PureComponent { /* Input widget for text labels, which acts like an InputGroup, but will also accept a suggestion list (of labels), with sublime-like suggest search. @@ -30,11 +26,9 @@ export default class LabelInput extends React.PureComponent<{}, State> { /* maxinum number of suggestions */ static QueryResultLimit = 100; - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + constructor(props) { super(props); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'label' does not exist on type '{}'. const { label } = props; const query = label || ""; const queryResults = this.filterLabels(query); @@ -44,8 +38,7 @@ export default class LabelInput extends React.PureComponent<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleQueryChange = (query: any, event: any) => { + handleQueryChange = (query, event) => { // https://github.com/palantir/blueprint/issues/2983 if (!event) return; @@ -55,23 +48,19 @@ export default class LabelInput extends React.PureComponent<{}, State> { queryResults, }); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onChange' does not exist on type 'Readon... Remove this comment to see the full error message const { onChange } = this.props; if (onChange) onChange(query, event); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleItemSelect = (item: any, event: any) => { + handleItemSelect = (item, event) => { /* only report the select if not already reported via onChange() */ const { target } = item; const { query } = this.state; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onSelect' does not exist on type 'Readon... Remove this comment to see the full error message const { onSelect } = this.props; if (target !== query && onSelect) onSelect(target, event); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleKeyDown = (e: any) => { + handleKeyDown = (e) => { /* prevent these events from propagating to containing form/dialog and causing further side effects (eg, closing dialog, submitting @@ -86,22 +75,13 @@ export default class LabelInput extends React.PureComponent<{}, State> { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleChange = (e: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'onChange' does not exist on type 'Readon... Remove this comment to see the full error message + handleChange = (e) => { const { onChange } = this.props; if (onChange) onChange(e.target.value); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - renderLabelSuggestion = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - queryResult: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - { handleClick, modifiers }: any - ) => { + renderLabelSuggestion = (queryResult, { handleClick, modifiers }) => { if (queryResult.newLabel) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'newLabelMessage' does not exist on type ... Remove this comment to see the full error message const { newLabelMessage } = this.props; return ( { ); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - filterLabels(query: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'labelSuggestions' does not exist on type... Remove this comment to see the full error message + filterLabels(query) { const { labelSuggestions } = this.props; if (!labelSuggestions) return []; /* empty query is wildcard */ if (query === "") { - return ( - labelSuggestions - .slice(0, LabelInput.QueryResultLimit) - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - .map((l: any) => ({ - target: l, - score: -10000, - })) - ); + return labelSuggestions + .slice(0, LabelInput.QueryResultLimit) + .map((l) => ({ + target: l, + score: -10000, + })); } /* else, do a fuzzy query */ @@ -153,16 +128,13 @@ export default class LabelInput extends React.PureComponent<{}, State> { let queryResults = fuzzysort.go(query, labelSuggestions, options); /* exact match will always be first in list */ if (query !== "" && queryResults[0]?.target !== query) - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ target: any; newLabel: true; }' is not ass... Remove this comment to see the full error message queryResults = [{ target: query, newLabel: true }, ...queryResults]; return queryResults; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { props } = this; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'labelSuggestions' does not exist on type... Remove this comment to see the full error message const { labelSuggestions, label, autoFocus = true } = props; const suggestEnabled = !!labelSuggestions && labelSuggestions.length > 0; @@ -170,8 +142,7 @@ export default class LabelInput extends React.PureComponent<{}, State> { return ( @@ -180,12 +151,10 @@ export default class LabelInput extends React.PureComponent<{}, State> { const popoverProps = { minimal: true, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - ...(props as any).popoverProps, + ...props.popoverProps, }; const inputProps = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - ...(props as any).inputProps, + ...props.inputProps, autoFocus: false, }; const { queryResults } = this.state; @@ -201,7 +170,6 @@ export default class LabelInput extends React.PureComponent<{}, State> { onQueryChange={this.handleQueryChange} popoverProps={popoverProps} inputProps={inputProps} - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ fill: true; inputValueRenderer: (i: any) =... Remove this comment to see the full error message onKeyDown={this.handleKeyDown} /> diff --git a/client/src/components/leftSidebar/index.tsx b/client/src/components/leftSidebar/index.js similarity index 58% rename from client/src/components/leftSidebar/index.tsx rename to client/src/components/leftSidebar/index.js index 19d71d4a..6d72b424 100644 --- a/client/src/components/leftSidebar/index.tsx +++ b/client/src/components/leftSidebar/index.js @@ -6,17 +6,12 @@ import DynamicScatterplot from "../scatterplot/scatterplot"; import TopLeftLogoAndTitle from "./topLeftLogoAndTitle"; import Continuous from "../continuous/continuous"; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor, + scatterplotXXaccessor: state.controls.scatterplotXXaccessor, + scatterplotYYaccessor: state.controls.scatterplotYYaccessor, })) class LeftSideBar extends React.Component { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message const { scatterplotXXaccessor, scatterplotYYaccessor } = this.props; return (
      { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'libraryVersions' does not exist on type ... Remove this comment to see the full error message const { libraryVersions, tosURL, privacyURL } = props; return ( { + const { corpora_props: corporaProps } = state.config; + const correctVersion = + ["1.0.0", "1.1.0"].indexOf(corporaProps?.version?.corpora_schema_version) > + -1; + return { + datasetTitle: state.config?.displayNames?.dataset ?? "", + libraryVersions: state.config?.library_versions, + aboutLink: state.config?.links?.["about-dataset"], + tosURL: state.config?.parameters?.about_legal_tos, + privacyURL: state.config?.parameters?.about_legal_privacy, + title: correctVersion ? corporaProps?.title : undefined, + }; +}) +class LeftSideBar extends React.Component { + handleClick = () => { + const { dispatch } = this.props; + dispatch({ type: "toggle dataset drawer" }); + }; + + render() { + const { + datasetTitle, + libraryVersions, + aboutLink, + privacyURL, + tosURL, + dispatch, + title, + } = this.props; + + return ( +
      +
      + + + cell + + × + + gene + +
      +
      + + + +
      +
      + ); + } +} + +export default LeftSideBar; diff --git a/client/src/components/leftSidebar/topLeftLogoAndTitle.tsx b/client/src/components/leftSidebar/topLeftLogoAndTitle.tsx deleted file mode 100644 index 8eb407d2..00000000 --- a/client/src/components/leftSidebar/topLeftLogoAndTitle.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { Button } from "@blueprintjs/core"; - -import * as globals from "../../globals"; -import Logo from "../framework/logo"; -import Truncate from "../util/truncate"; -import InfoDrawer from "../infoDrawer/infoDrawer"; -import InformationMenu from "./infoMenu"; - -const DATASET_TITLE_FONT_SIZE = 14; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const { corpora_props: corporaProps } = (state as any).config; - const correctVersion = - ["1.0.0", "1.1.0"].indexOf(corporaProps?.version?.corpora_schema_version) > - -1; - return { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - datasetTitle: (state as any).config?.displayNames?.dataset ?? "", - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - libraryVersions: (state as any).config?.library_versions, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - aboutLink: (state as any).config?.links?.["about-dataset"], - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - tosURL: (state as any).config?.parameters?.about_legal_tos, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - privacyURL: (state as any).config?.parameters?.about_legal_privacy, - title: correctVersion ? corporaProps?.title : undefined, - }; -}) -class LeftSideBar extends React.Component { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleClick = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch({ type: "toggle dataset drawer" }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'datasetTitle' does not exist on type 'Re... Remove this comment to see the full error message - datasetTitle, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'libraryVersions' does not exist on type ... Remove this comment to see the full error message - libraryVersions, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'aboutLink' does not exist on type 'Reado... Remove this comment to see the full error message - aboutLink, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'privacyURL' does not exist on type 'Read... Remove this comment to see the full error message - privacyURL, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message - tosURL, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - dispatch, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'title' does not exist on type 'Readonly<... Remove this comment to see the full error message - title, - } = this.props; - - return ( -
      -
      - - - cell - - × - - gene - -
      -
      - - - -
      -
      - ); - } -} - -export default LeftSideBar; diff --git a/client/src/components/menubar/authButtons.tsx b/client/src/components/menubar/authButtons.js similarity index 81% rename from client/src/components/menubar/authButtons.tsx rename to client/src/components/menubar/authButtons.js index 28f3d616..91af0b42 100644 --- a/client/src/components/menubar/authButtons.tsx +++ b/client/src/components/menubar/authButtons.js @@ -17,7 +17,6 @@ import { IconNames } from "@blueprintjs/icons"; import * as globals from "../../globals"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message import styles from "./menubar.css"; import { storageGet, storageSet, KEYS } from "../util/localStorage"; @@ -32,13 +31,11 @@ const LOGIN_PROMPT_OFF = "off"; const Auth = React.memo((props) => { const [isPromptOpen, setIsPromptOpen] = useState(shouldShowPrompt()); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'auth' does not exist on type '{ children... Remove this comment to see the full error message const { auth, userInfo } = props; const isAuthenticated = userInfo && userInfo.is_authenticated; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (window as any).userInfo = userInfo; + window.userInfo = userInfo; const randomInt = Math.random() * 15; const sexIndex = Math.floor(randomInt / 5); @@ -78,7 +75,6 @@ const Auth = React.memo((props) => { > {/* eslint-disable-next-line no-constant-condition -- disable profile picture until CSP is tweaked */} {userInfo?.picture && false ? ( - // @ts-expect-error ts-migrate(2322) FIXME: Type '{ alt: string; size: string; src: any; }' is... Remove this comment to see the full error message profile ) : ( {scientist} @@ -127,13 +123,11 @@ const Auth = React.memo((props) => { function shouldShowPrompt() { if (storageGet(KEYS.LOGIN_PROMPT) === LOGIN_PROMPT_OFF) return false; - // @ts-expect-error ts-migrate(2774) FIXME: This condition will always return true since the f... Remove this comment to see the full error message return shouldShowAuth && !isAuthenticated; } }); -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function PromptContent({ setIsPromptOpen }: any) { +function PromptContent({ setIsPromptOpen }) { const [isChecked, setIsChecked] = useState(false); function handleOKClick() { diff --git a/client/src/components/menubar/cellSetButtons.tsx b/client/src/components/menubar/cellSetButtons.js similarity index 60% rename from client/src/components/menubar/cellSetButtons.tsx rename to client/src/components/menubar/cellSetButtons.js index 3f4b645f..f1d915a4 100644 --- a/client/src/components/menubar/cellSetButtons.tsx +++ b/client/src/components/menubar/cellSetButtons.js @@ -4,22 +4,17 @@ import { connect } from "react-redux"; import { tooltipHoverOpenDelay } from "../../globals"; import actions from "../../actions"; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - differential: (state as any).differential, + differential: state.differential, })) class CellSetButton extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. set() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, eitherCellSetOneOrTwo } = this.props; + dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo)); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'differential' does not exist on type 'Re... Remove this comment to see the full error message const { differential, eitherCellSetOneOrTwo } = this.props; const cellListName = `celllist${eitherCellSetOneOrTwo}`; const cellsSelected = differential[cellListName] diff --git a/client/src/components/menubar/clip.tsx b/client/src/components/menubar/clip.js similarity index 68% rename from client/src/components/menubar/clip.tsx rename to client/src/components/menubar/clip.js index cf1558c6..5bc1d18d 100644 --- a/client/src/components/menubar/clip.tsx +++ b/client/src/components/menubar/clip.js @@ -12,30 +12,19 @@ import { import { IconNames } from "@blueprintjs/icons"; import { tooltipHoverOpenDelay } from "../../globals"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message import styles from "./menubar.css"; const Clip = React.memo((props) => { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'pendingClipPercentiles' does not exist o... Remove this comment to see the full error message pendingClipPercentiles, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message clipPercentileMin, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message clipPercentileMax, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipOpening' does not exist on typ... Remove this comment to see the full error message handleClipOpening, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipClosing' does not exist on typ... Remove this comment to see the full error message handleClipClosing, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipCommit' does not exist on type... Remove this comment to see the full error message handleClipCommit, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'isClipDisabled' does not exist on type '... Remove this comment to see the full error message isClipDisabled, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipOnKeyPress' does not exist on ... Remove this comment to see the full error message handleClipOnKeyPress, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipPercentileMaxValueChange' does... Remove this comment to see the full error message handleClipPercentileMaxValueChange, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleClipPercentileMinValueChange' does... Remove this comment to see the full error message handleClipPercentileMinValueChange, } = props; @@ -45,8 +34,7 @@ const Clip = React.memo((props) => { pendingClipPercentiles?.clipPercentileMax ?? clipPercentileMax; const intent = clipPercentileMin > 0 || clipPercentileMax < 100 - ? // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (Intent as any).INTENT_WARNING + ? Intent.INTENT_WARNING : Intent.NONE; return ( diff --git a/client/src/components/menubar/diffexpButtons.tsx b/client/src/components/menubar/diffexpButtons.js similarity index 60% rename from client/src/components/menubar/diffexpButtons.tsx rename to client/src/components/menubar/diffexpButtons.js index 823639ab..a94890ac 100644 --- a/client/src/components/menubar/diffexpButtons.tsx +++ b/client/src/components/menubar/diffexpButtons.js @@ -2,25 +2,17 @@ import React from "react"; import { connect } from "react-redux"; import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core"; import * as globals from "../../globals"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message import styles from "./menubar.css"; import actions from "../../actions"; import CellSetButton from "./cellSetButtons"; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - differential: (state as any).differential, - diffexpMayBeSlow: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.["diffexp-may-be-slow"] ?? false, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - diffexpCellcountMax: (state as any).config?.limits?.diffexp_cellcount_max, + differential: state.differential, + diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false, + diffexpCellcountMax: state.config?.limits?.diffexp_cellcount_max, })) class DiffexpButtons extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. computeDiffExp = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message const { dispatch, differential } = this.props; if (differential.celllist1 && differential.celllist2) { dispatch( @@ -32,32 +24,33 @@ class DiffexpButtons extends React.PureComponent { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { /* diffexp-related buttons may be disabled */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'differential' does not exist on type 'Re... Remove this comment to see the full error message const { differential, diffexpMayBeSlow, diffexpCellcountMax } = this.props; + const haveBothCellSets = !!differential.celllist1 && !!differential.celllist2; + const haveEitherCellSet = !!differential.celllist1 || !!differential.celllist2; + const slowMsg = diffexpMayBeSlow ? " (CAUTION: large dataset - may take longer or fail)" : ""; const tipMessage = `See top 10 differentially expressed genes${slowMsg}`; const tipMessageWarn = `The total number of cells for differential expression computation may not exceed ${diffexpCellcountMax}. Try reselecting new cell sets.`; + const warnMaxSizeExceeded = haveEitherCellSet && !!diffexpCellcountMax && (differential.celllist1?.length ?? 0) + (differential.celllist2?.length ?? 0) > diffexpCellcountMax; + return ( - {/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */} - {/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */} { + const { annoMatrix } = state; + const crossfilter = state.obsCrossfilter; + const selectedCount = crossfilter.countSelected(); + + const subsetPossible = + selectedCount !== 0 && selectedCount !== crossfilter.size(); // ie, not all and not none are selected + const embSubsetView = getEmbSubsetView(annoMatrix); + const subsetResetPossible = !embSubsetView + ? annoMatrix.nObs !== annoMatrix.schema.dataframe.nObs + : annoMatrix.nObs !== embSubsetView.nObs; + + return { + subsetPossible, + subsetResetPossible, + graphInteractionMode: state.controls.graphInteractionMode, + clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)), + clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)), + userDefinedGenes: state.controls.userDefinedGenes, + colorAccessor: state.colors.colorAccessor, + scatterplotXXaccessor: state.controls.scatterplotXXaccessor, + scatterplotYYaccessor: state.controls.scatterplotYYaccessor, + libraryVersions: state.config?.library_versions, + auth: state.config?.authentication, + userInfo: state.userInfo, + undoDisabled: state["@@undoable/past"].length === 0, + redoDisabled: state["@@undoable/future"].length === 0, + aboutLink: state.config?.links?.["about-dataset"], + disableDiffexp: state.config?.parameters?.["disable-diffexp"] ?? false, + diffexpMayBeSlow: + state.config?.parameters?.["diffexp-may-be-slow"] ?? false, + showCentroidLabels: state.centroidLabels.showLabels, + tosURL: state.config?.parameters?.about_legal_tos, + privacyURL: state.config?.parameters?.about_legal_privacy, + categoricalSelection: state.categoricalSelection, + }; +}) +class MenuBar extends React.PureComponent { + static isValidDigitKeyEvent(e) { + /* + Return true if this event is necessary to enter a percent number input. + Return false if not. + + Returns true for events with keys: backspace, control, alt, meta, [0-9], + or events that don't have a key. + */ + if (e.key === null) return true; + if (e.ctrlKey || e.altKey || e.metaKey) return true; + + // concept borrowed from blueprint's numericInputUtils: + // keys that print a single character when pressed have a `key` name of + // length 1. every other key has a longer `key` name (e.g. "Backspace", + // "ArrowUp", "Shift"). since none of those keys can print a character + // to the field--and since they may have important native behaviors + // beyond printing a character--we don't want to disable their effects. + const isSingleCharKey = e.key.length === 1; + if (!isSingleCharKey) return true; + + const key = e.key.charCodeAt(0) - 48; /* "0" */ + return key >= 0 && key <= 9; + } + + constructor(props) { + super(props); + this.state = { + pendingClipPercentiles: null, + }; + } + + isClipDisabled = () => { + /* + return true if clip button should be disabled. + */ + const { pendingClipPercentiles } = this.state; + const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin; + const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax; + const { + clipPercentileMin: currentClipMin, + clipPercentileMax: currentClipMax, + } = this.props; + + // if you change this test, be careful with logic around + // comparisons between undefined / NaN handling. + const isDisabled = + !(clipPercentileMin < clipPercentileMax) || + (clipPercentileMin === currentClipMin && + clipPercentileMax === currentClipMax); + + return isDisabled; + }; + + handleClipOnKeyPress = (e) => { + /* + allow only numbers, plus other critical keys which + may be required to make a number + */ + if (!MenuBar.isValidDigitKeyEvent(e)) { + e.preventDefault(); + } + }; + + handleClipPercentileMinValueChange = (v) => { + /* + Ignore anything that isn't a legit number + */ + if (!Number.isFinite(v)) return; + + const { pendingClipPercentiles } = this.state; + const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax; + + /* + clamp to [0, currentClipPercentileMax] + */ + if (v <= 0) v = 0; + if (v > 100) v = 100; + const clipPercentileMin = Math.round(v); // paranoia + this.setState({ + pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, + }); + }; + + handleClipPercentileMaxValueChange = (v) => { + /* + Ignore anything that isn't a legit number + */ + if (!Number.isFinite(v)) return; + + const { pendingClipPercentiles } = this.state; + const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin; + + /* + clamp to [0, 100] + */ + if (v < 0) v = 0; + if (v > 100) v = 100; + const clipPercentileMax = Math.round(v); // paranoia + + this.setState({ + pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, + }); + }; + + handleClipCommit = () => { + const { dispatch } = this.props; + const { pendingClipPercentiles } = this.state; + const { clipPercentileMin, clipPercentileMax } = pendingClipPercentiles; + const min = clipPercentileMin / 100; + const max = clipPercentileMax / 100; + dispatch(actions.clipAction(min, max)); + }; + + handleClipOpening = () => { + const { clipPercentileMin, clipPercentileMax } = this.props; + this.setState({ + pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, + }); + }; + + handleClipClosing = () => { + this.setState({ pendingClipPercentiles: null }); + }; + + handleCentroidChange = () => { + const { dispatch, showCentroidLabels } = this.props; + + dispatch({ + type: "show centroid labels for category", + showLabels: !showCentroidLabels, + }); + }; + + handleSubset = () => { + const { dispatch } = this.props; + dispatch(actions.subsetAction()); + }; + + handleSubsetReset = () => { + const { dispatch } = this.props; + dispatch(actions.resetSubsetAction()); + }; + + render() { + const { + dispatch, + disableDiffexp, + undoDisabled, + redoDisabled, + selectionTool, + clipPercentileMin, + clipPercentileMax, + graphInteractionMode, + showCentroidLabels, + categoricalSelection, + colorAccessor, + subsetPossible, + subsetResetPossible, + userInfo, + auth, + } = this.props; + const { pendingClipPercentiles } = this.state; + + const isColoredByCategorical = !!categoricalSelection?.[colorAccessor]; + + // constants used to create selection tool button + const [selectionTooltip, selectionButtonIcon] = + selectionTool === "brush" + ? ["Brush selection", "Lasso selection"] + : ["select", "polygon-filter"]; + + return ( +
      + + + + + + + + + { + dispatch({ + type: "change graph interaction mode", + data: "select", + }); + }} + /> + + + { + dispatch({ + type: "change graph interaction mode", + data: "zoom", + }); + }} + /> + + + + {disableDiffexp ? null : } +
      + ); + } +} + +export default MenuBar; diff --git a/client/src/components/menubar/index.tsx b/client/src/components/menubar/index.tsx deleted file mode 100644 index 3c54805f..00000000 --- a/client/src/components/menubar/index.tsx +++ /dev/null @@ -1,392 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core"; - -import * as globals from "../../globals"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message -import styles from "./menubar.css"; -import actions from "../../actions"; -import Clip from "./clip"; - -import AuthButtons from "./authButtons"; -import Subset from "./subset"; -import UndoRedoReset from "./undoRedo"; -import DiffexpButtons from "./diffexpButtons"; -import { getEmbSubsetView } from "../../util/stateManager/viewStackHelpers"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message -@connect((state) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Defa... Remove this comment to see the full error message - const { annoMatrix } = state; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const crossfilter = (state as any).obsCrossfilter; - const selectedCount = crossfilter.countSelected(); - - const subsetPossible = - selectedCount !== 0 && selectedCount !== crossfilter.size(); // ie, not all and not none are selected - const embSubsetView = getEmbSubsetView(annoMatrix); - const subsetResetPossible = !embSubsetView - ? annoMatrix.nObs !== annoMatrix.schema.dataframe.nObs - : annoMatrix.nObs !== embSubsetView.nObs; - - return { - subsetPossible, - subsetResetPossible, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - graphInteractionMode: (state as any).controls.graphInteractionMode, - clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)), - clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)), - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userDefinedGenes: (state as any).controls.userDefinedGenes, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorAccessor: (state as any).colors.colorAccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - libraryVersions: (state as any).config?.library_versions, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - auth: (state as any).config?.authentication, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userInfo: (state as any).userInfo, - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - undoDisabled: state["@@undoable/past"].length === 0, - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - redoDisabled: state["@@undoable/future"].length === 0, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - aboutLink: (state as any).config?.links?.["about-dataset"], - disableDiffexp: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.["disable-diffexp"] ?? false, - diffexpMayBeSlow: - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (state as any).config?.parameters?.["diffexp-may-be-slow"] ?? false, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - showCentroidLabels: (state as any).centroidLabels.showLabels, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - tosURL: (state as any).config?.parameters?.about_legal_tos, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - privacyURL: (state as any).config?.parameters?.about_legal_privacy, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoricalSelection: (state as any).categoricalSelection, - }; -}) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class MenuBar extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static isValidDigitKeyEvent(e: any) { - /* - Return true if this event is necessary to enter a percent number input. - Return false if not. - - Returns true for events with keys: backspace, control, alt, meta, [0-9], - or events that don't have a key. - */ - if (e.key === null) return true; - if (e.ctrlKey || e.altKey || e.metaKey) return true; - - // concept borrowed from blueprint's numericInputUtils: - // keys that print a single character when pressed have a `key` name of - // length 1. every other key has a longer `key` name (e.g. "Backspace", - // "ArrowUp", "Shift"). since none of those keys can print a character - // to the field--and since they may have important native behaviors - // beyond printing a character--we don't want to disable their effects. - const isSingleCharKey = e.key.length === 1; - if (!isSingleCharKey) return true; - - const key = e.key.charCodeAt(0) - 48; /* "0" */ - return key >= 0 && key <= 9; - } - - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { - super(props); - this.state = { - pendingClipPercentiles: null, - }; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - isClipDisabled = () => { - /* - return true if clip button should be disabled. - */ - const { pendingClipPercentiles } = this.state; - const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin; - const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax; - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message - clipPercentileMin: currentClipMin, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message - clipPercentileMax: currentClipMax, - } = this.props; - - // if you change this test, be careful with logic around - // comparisons between undefined / NaN handling. - const isDisabled = - !(clipPercentileMin < clipPercentileMax) || - (clipPercentileMin === currentClipMin && - clipPercentileMax === currentClipMax); - - return isDisabled; - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleClipOnKeyPress = (e: any) => { - /* - allow only numbers, plus other critical keys which - may be required to make a number - */ - if (!MenuBar.isValidDigitKeyEvent(e)) { - e.preventDefault(); - } - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleClipPercentileMinValueChange = (v: any) => { - /* - Ignore anything that isn't a legit number - */ - if (!Number.isFinite(v)) return; - - const { pendingClipPercentiles } = this.state; - const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax; - - /* - clamp to [0, currentClipPercentileMax] - */ - if (v <= 0) v = 0; - if (v > 100) v = 100; - const clipPercentileMin = Math.round(v); // paranoia - this.setState({ - pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - handleClipPercentileMaxValueChange = (v: any) => { - /* - Ignore anything that isn't a legit number - */ - if (!Number.isFinite(v)) return; - - const { pendingClipPercentiles } = this.state; - const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin; - - /* - clamp to [0, 100] - */ - if (v < 0) v = 0; - if (v > 100) v = 100; - const clipPercentileMax = Math.round(v); // paranoia - - this.setState({ - pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleClipCommit = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - const { pendingClipPercentiles } = this.state; - const { clipPercentileMin, clipPercentileMax } = pendingClipPercentiles; - const min = clipPercentileMin / 100; - const max = clipPercentileMax / 100; - dispatch(actions.clipAction(min, max)); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleClipOpening = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message - const { clipPercentileMin, clipPercentileMax } = this.props; - this.setState({ - pendingClipPercentiles: { clipPercentileMin, clipPercentileMax }, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleClipClosing = () => { - this.setState({ pendingClipPercentiles: null }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleCentroidChange = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch, showCentroidLabels } = this.props; - - dispatch({ - type: "show centroid labels for category", - showLabels: !showCentroidLabels, - }); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleSubset = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch(actions.subsetAction()); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - handleSubsetReset = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - const { dispatch } = this.props; - dispatch(actions.resetSubsetAction()); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message - dispatch, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'disableDiffexp' does not exist on type '... Remove this comment to see the full error message - disableDiffexp, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'undoDisabled' does not exist on type 'Re... Remove this comment to see the full error message - undoDisabled, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'redoDisabled' does not exist on type 'Re... Remove this comment to see the full error message - redoDisabled, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message - selectionTool, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMin' does not exist on typ... Remove this comment to see the full error message - clipPercentileMin, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'clipPercentileMax' does not exist on typ... Remove this comment to see the full error message - clipPercentileMax, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message - graphInteractionMode, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'showCentroidLabels' does not exist on ty... Remove this comment to see the full error message - showCentroidLabels, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message - categoricalSelection, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message - colorAccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetPossible' does not exist on type '... Remove this comment to see the full error message - subsetPossible, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetResetPossible' does not exist on t... Remove this comment to see the full error message - subsetResetPossible, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'userInfo' does not exist on type 'Readon... Remove this comment to see the full error message - userInfo, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'auth' does not exist on type 'Readonly<{... Remove this comment to see the full error message - auth, - } = this.props; - const { pendingClipPercentiles } = this.state; - - const isColoredByCategorical = !!categoricalSelection?.[colorAccessor]; - - // constants used to create selection tool button - const [selectionTooltip, selectionButtonIcon] = - selectionTool === "brush" - ? ["Brush selection", "Lasso selection"] - : ["select", "polygon-filter"]; - - return ( -
      - - - - - - - - - { - dispatch({ - type: "change graph interaction mode", - data: "select", - }); - }} - /> - - - { - dispatch({ - type: "change graph interaction mode", - data: "zoom", - }); - }} - /> - - - - {disableDiffexp ? null : } -
      - ); - } -} - -export default MenuBar; diff --git a/client/src/components/menubar/subset.tsx b/client/src/components/menubar/subset.js similarity index 62% rename from client/src/components/menubar/subset.tsx rename to client/src/components/menubar/subset.js index ca96329e..03025cb3 100644 --- a/client/src/components/menubar/subset.tsx +++ b/client/src/components/menubar/subset.js @@ -1,18 +1,13 @@ import React from "react"; import { AnchorButton, ButtonGroup, Tooltip } from "@blueprintjs/core"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message import styles from "./menubar.css"; import * as globals from "../../globals"; const Subset = React.memo((props) => { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetPossible' does not exist on type '... Remove this comment to see the full error message subsetPossible, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'subsetResetPossible' does not exist on t... Remove this comment to see the full error message subsetResetPossible, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubset' does not exist on type '{ ... Remove this comment to see the full error message handleSubset, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'handleSubsetReset' does not exist on typ... Remove this comment to see the full error message handleSubsetReset, } = props; diff --git a/client/src/components/menubar/undoRedo.tsx b/client/src/components/menubar/undoRedo.js similarity index 81% rename from client/src/components/menubar/undoRedo.tsx rename to client/src/components/menubar/undoRedo.js index 39c8ea5d..8591505c 100644 --- a/client/src/components/menubar/undoRedo.tsx +++ b/client/src/components/menubar/undoRedo.js @@ -2,11 +2,9 @@ import React from "react"; import { AnchorButton, ButtonGroup, Tooltip } from "@blueprintjs/core"; import { IconNames } from "@blueprintjs/icons"; import { tooltipHoverOpenDelay } from "../../globals"; -// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module './menubar.css' or its correspo... Remove this comment to see the full error message import styles from "./menubar.css"; const UndoRedo = React.memo((props) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'undoDisabled' does not exist on type '{ ... Remove this comment to see the full error message const { undoDisabled, redoDisabled, dispatch } = props; return ( diff --git a/client/src/components/miniHistogram/index.tsx b/client/src/components/miniHistogram/index.js similarity index 53% rename from client/src/components/miniHistogram/index.tsx rename to client/src/components/miniHistogram/index.js index fc9bd4fb..d5e9b44e 100644 --- a/client/src/components/miniHistogram/index.tsx +++ b/client/src/components/miniHistogram/index.js @@ -7,18 +7,12 @@ import { } from "@blueprintjs/core"; export default class MiniHistogram extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - canvasRef: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(props: any) { + constructor(props) { super(props); this.canvasRef = React.createRef(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. drawHistogram = () => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'xScale' does not exist on type 'Readonly... Remove this comment to see the full error message const { xScale, yScale, bins, width, height } = this.props; if (!bins) return; @@ -41,14 +35,11 @@ export default class MiniHistogram extends React.PureComponent { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount = () => { this.drawHistogram(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - componentDidUpdate = (prevProps: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'obsOrVarContinuousFieldDisplayName' does... Remove this comment to see the full error message + componentDidUpdate = (prevProps) => { const { obsOrVarContinuousFieldDisplayName, bins } = this.props; if ( prevProps.obsOrVarContinuousFieldDisplayName !== @@ -58,18 +49,9 @@ export default class MiniHistogram extends React.PureComponent { this.drawHistogram(); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'domainLabel' does not exist on type 'Rea... Remove this comment to see the full error message - domainLabel, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'obsOrVarContinuousFieldDisplayName' does... Remove this comment to see the full error message - obsOrVarContinuousFieldDisplayName, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message - width, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message - height, - } = this.props; + const { domainLabel, obsOrVarContinuousFieldDisplayName, width, height } = + this.props; return ( { + const { + domainValues, + scale, + domain, + colorTable, + occupancy, + width, + height, + } = this.props; + + if (!colorTable || !domainValues) return; + + const { scale: colorScale } = colorTable; + + const ctx = this.canvasRef?.current.getContext("2d"); + + ctx.clearRect(0, 0, width, height); + let currentOffset = 0; + + let occupancyValue; + let scaledValue; + let value; + + for (let i = 0, { length } = domainValues; i < length; i += 1) { + value = domainValues[i]; + occupancyValue = occupancy.get(value); + scaledValue = scale(occupancyValue); + ctx.fillStyle = occupancyValue + ? colorScale(domain.indexOf(value)) + : "rgb(255,255,255)"; + ctx.fillRect(currentOffset, 0, occupancyValue ? scaledValue : 0, height); + currentOffset += occupancyValue ? scaledValue : 0; + } + }; + + componentDidUpdate = (prevProps) => { + const { occupancy } = this.props; + if (occupancy !== prevProps.occupancy) this.drawStacks(); + }; + + componentDidMount = () => { + this.drawStacks(); + }; + + render() { + const { width, height } = this.props; + const { canvas } = this; + if (canvas) canvas.getContext("2d").clearRect(0, 0, width, height); + + return ( + + ); + } +} diff --git a/client/src/components/miniStackedBar/index.tsx b/client/src/components/miniStackedBar/index.tsx deleted file mode 100644 index 7f6a959f..00000000 --- a/client/src/components/miniStackedBar/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from "react"; - -export default class MiniStackedBar extends React.PureComponent { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - canvasRef: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(props: any) { - super(props); - this.canvasRef = React.createRef(); - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - drawStacks = () => { - const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'domainValues' does not exist on type 'Re... Remove this comment to see the full error message - domainValues, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'Readonly<... Remove this comment to see the full error message - scale, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'domain' does not exist on type 'Readonly... Remove this comment to see the full error message - domain, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message - colorTable, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'occupancy' does not exist on type 'Reado... Remove this comment to see the full error message - occupancy, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message - width, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message - height, - } = this.props; - - if (!colorTable || !domainValues) return; - - const { scale: colorScale } = colorTable; - - const ctx = this.canvasRef?.current.getContext("2d"); - - ctx.clearRect(0, 0, width, height); - let currentOffset = 0; - - let occupancyValue; - let scaledValue; - let value; - - for (let i = 0, { length } = domainValues; i < length; i += 1) { - value = domainValues[i]; - occupancyValue = occupancy.get(value); - scaledValue = scale(occupancyValue); - ctx.fillStyle = occupancyValue - ? colorScale(domain.indexOf(value)) - : "rgb(255,255,255)"; - ctx.fillRect(currentOffset, 0, occupancyValue ? scaledValue : 0, height); - currentOffset += occupancyValue ? scaledValue : 0; - } - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - componentDidUpdate = (prevProps: any) => { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'occupancy' does not exist on type 'Reado... Remove this comment to see the full error message - const { occupancy } = this.props; - if (occupancy !== prevProps.occupancy) this.drawStacks(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - componentDidMount = () => { - this.drawStacks(); - }; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - render() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message - const { width, height } = this.props; - // @ts-expect-error ts-migrate(2339) FIXME: Property 'canvas' does not exist on type 'MiniStac... Remove this comment to see the full error message - const { canvas } = this; - if (canvas) canvas.getContext("2d").clearRect(0, 0, width, height); - - return ( - - ); - } -} diff --git a/client/src/components/rightSidebar/index.tsx b/client/src/components/rightSidebar/index.js similarity index 52% rename from client/src/components/rightSidebar/index.tsx rename to client/src/components/rightSidebar/index.js index baaf23a0..43802b99 100644 --- a/client/src/components/rightSidebar/index.tsx +++ b/client/src/components/rightSidebar/index.js @@ -3,15 +3,11 @@ import { connect } from "react-redux"; import GeneExpression from "../geneExpression"; import * as globals from "../../globals"; -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotXXaccessor: (state as any).controls.scatterplotXXaccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - scatterplotYYaccessor: (state as any).controls.scatterplotYYaccessor, + scatterplotXXaccessor: state.controls.scatterplotXXaccessor, + scatterplotYYaccessor: state.controls.scatterplotYYaccessor, })) class RightSidebar extends React.Component { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { return (
      { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message const { obsCrossfilter: crossfilter } = state; - const { - scatterplotXXaccessor, - scatterplotYYaccessor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - } = (state as any).controls; + const { scatterplotXXaccessor, scatterplotYYaccessor } = state.controls; return { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - annoMatrix: (state as any).annoMatrix, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colors: (state as any).colors, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - pointDilation: (state as any).pointDilation, + annoMatrix: state.annoMatrix, + colors: state.colors, + pointDilation: state.pointDilation, + // Accessors are var/gene names (strings) scatterplotXXaccessor, scatterplotYYaccessor, + crossfilter, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - genesets: (state as any).genesets.genesets, + genesets: state.genesets.genesets, }; }) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class Scatterplot extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static createReglState(canvas: any) { +class Scatterplot extends React.PureComponent { + static createReglState(canvas) { /* Must be created for each canvas */ @@ -87,11 +70,8 @@ class Scatterplot extends React.PureComponent<{}, State> { const drawPoints = _drawPoints(regl); // preallocate webgl buffers - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const pointBuffer = regl.buffer(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const colorBuffer = regl.buffer(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const flagBuffer = regl.buffer(); return { @@ -103,20 +83,10 @@ class Scatterplot extends React.PureComponent<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static watchAsync(props: any, prevProps: any) { + static watchAsync(props, prevProps) { return !shallowEqual(props.watchProps, prevProps.watchProps); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - axes: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - reglCanvas: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - renderCache: any; - computePointPositions = memoize((X, Y, xScale, yScale) => { const positions = new Float32Array(2 * X.length); for (let i = 0, len = X.length; i < len; i += 1) { @@ -213,8 +183,7 @@ class Scatterplot extends React.PureComponent<{}, State> { } ); - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { + constructor(props) { super(props); const viewport = this.getViewportDimensions(); this.axes = false; @@ -229,19 +198,16 @@ class Scatterplot extends React.PureComponent<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount() { // this affect point render size for the scatterplot window.addEventListener("resize", this.handleResize); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentWillUnmount() { window.removeEventListener("resize", this.handleResize); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - setReglCanvas = (canvas: any) => { + setReglCanvas = (canvas) => { this.reglCanvas = canvas; if (canvas) { // no need to update this state if we are detaching. @@ -251,13 +217,11 @@ class Scatterplot extends React.PureComponent<{}, State> { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. getViewportDimensions = () => ({ - height: window.innerHeight, - width: window.innerWidth, - }); + height: window.innerHeight, + width: window.innerWidth, + }); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleResize = () => { const { state } = this.state; const viewport = this.getViewportDimensions(); @@ -267,8 +231,7 @@ class Scatterplot extends React.PureComponent<{}, State> { }); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fetchAsyncProps = async (props: any) => { + fetchAsyncProps = async (props) => { const { scatterplotXXaccessor, scatterplotYYaccessor, @@ -326,9 +289,7 @@ class Scatterplot extends React.PureComponent<{}, State> { }; }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - createXQuery(geneName: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + createXQuery(geneName) { const { annoMatrix } = this.props; const { schema } = annoMatrix; const varIndex = schema?.annotations?.var?.index; @@ -345,19 +306,15 @@ class Scatterplot extends React.PureComponent<{}, State> { ]; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - createColorByQuery(colors: any) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + createColorByQuery(colors) { const { annoMatrix, genesets } = this.props; const { schema } = annoMatrix; const { colorMode, colorAccessor } = colors; return createColorQuery(colorMode, colorAccessor, schema, genesets); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - updateColorTable(colors: any, colorDf: any) { + updateColorTable(colors, colorDf) { /* update color table state */ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message const { annoMatrix } = this.props; const { schema } = annoMatrix; const { colorAccessor, userColors, colorMode } = colors; @@ -370,42 +327,40 @@ class Scatterplot extends React.PureComponent<{}, State> { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. async fetchData( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - scatterplotXXaccessor: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - scatterplotYYaccessor: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colors: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - pointDilation: any - ): Promise< - [Dataframe, Dataframe, Dataframe | null, Dataframe | null] - > { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message + scatterplotXXaccessor, + scatterplotYYaccessor, + colors, + pointDilation + ) { const { annoMatrix } = this.props; const { metadataField: pointDilationAccessor } = pointDilation; + const promises = []; + // X and Y dimensions + promises.push( + annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor)) + ); + promises.push( + annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor)) + ); + + // color const query = this.createColorByQuery(colors); + if (query) { + promises.push(annoMatrix.fetch(...query)); + } else { + promises.push(Promise.resolve(null)); + } - const promises: [Dataframe, Dataframe, Dataframe | null, Dataframe | null] = - [ - // @ts-expect-error ts-migrate(2488) FIXME: Type '(string | { where: { field: string; column: ... Remove this comment to see the full error message - annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor)), - annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor)), - query ? annoMatrix.fetch(...query) : Promise.resolve(null), - pointDilationAccessor - ? annoMatrix.fetch("obs", pointDilationAccessor) - : Promise.resolve(null), - ]; + // point highlighting + if (pointDilationAccessor) { + promises.push(annoMatrix.fetch("obs", pointDilationAccessor)); + } else { + promises.push(Promise.resolve(null)); + } - return Promise.all< - Dataframe, - Dataframe, - Dataframe | null, - Dataframe | null - >(promises); + return Promise.all(promises); } renderCanvas = renderThrottle(() => { @@ -427,8 +382,7 @@ class Scatterplot extends React.PureComponent<{}, State> { ); }); - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - updateReglAndRender(newRenderCache: any) { + updateReglAndRender(newRenderCache) { const { positions, colors, flags } = newRenderCache; this.renderCache = newRenderCache; const { pointBuffer, colorBuffer, flagBuffer } = this.state; @@ -438,22 +392,14 @@ class Scatterplot extends React.PureComponent<{}, State> { this.renderCanvas(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderPoints( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - regl: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - drawPoints: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - flagBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - pointBuffer: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - projectionTF: any + regl, + drawPoints, + flagBuffer, + colorBuffer, + pointBuffer, + projectionTF ) { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message const { annoMatrix } = this.props; if (!this.reglCanvas || !annoMatrix) return; @@ -479,22 +425,14 @@ class Scatterplot extends React.PureComponent<{}, State> { regl._gl.flush(); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message dispatch, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message annoMatrix, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message scatterplotXXaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotYYaccessor' does not exist on... Remove this comment to see the full error message scatterplotYYaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message colors, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on type 'Rea... Remove this comment to see the full error message crossfilter, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on type 'R... Remove this comment to see the full error message pointDilation, } = this.props; const { minimized, regl, viewport } = this.state; @@ -561,7 +499,6 @@ class Scatterplot extends React.PureComponent<{}, State> { style={{ marginLeft: margin.left, marginTop: margin.top, - // @ts-expect-error ts-migrate(2322) FIXME: Type '"none" | null' is not assignable to type 'Di... Remove this comment to see the full error message display: minimized ? "none" : null, }} ref={this.setReglCanvas} @@ -588,14 +525,11 @@ class Scatterplot extends React.PureComponent<{}, State> { } return ( ); }} @@ -611,15 +545,10 @@ export default Scatterplot; const ScatterplotAxis = React.memo( ({ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'minimized' does not exist on type '{ chi... Remove this comment to see the full error message minimized, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotYYaccessor' does not exist on... Remove this comment to see the full error message scatterplotYYaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'scatterplotXXaccessor' does not exist on... Remove this comment to see the full error message scatterplotXXaccessor, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'xScale' does not exist on type '{ childr... Remove this comment to see the full error message xScale, - // @ts-expect-error ts-migrate(2339) FIXME: Property 'yScale' does not exist on type '{ childr... Remove this comment to see the full error message yScale, }) => { /* @@ -643,9 +572,7 @@ const ScatterplotAxis = React.memo( // the axes are much cleaner and easier now. No need to rotate and orient // the axis, just call axisBottom, axisLeft etc. - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const xAxis = d3.axisBottom().ticks(7).scale(xScale); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0. const yAxis = d3.axisLeft().ticks(7).scale(yScale); // adding axes is also simpler now, just translate x-axis to (0,height) @@ -688,7 +615,6 @@ const ScatterplotAxis = React.memo( height={height + margin.top + margin.bottom} data-testid="scatterplot-svg" style={{ - // @ts-expect-error ts-migrate(2322) FIXME: Type '"none" | null' is not assignable to type 'Di... Remove this comment to see the full error message display: minimized ? "none" : null, }} > diff --git a/client/src/components/scatterplot/util.ts b/client/src/components/scatterplot/util.js similarity index 100% rename from client/src/components/scatterplot/util.ts rename to client/src/components/scatterplot/util.js diff --git a/client/src/components/termsPrompt/index.tsx b/client/src/components/termsPrompt/index.js similarity index 53% rename from client/src/components/termsPrompt/index.tsx rename to client/src/components/termsPrompt/index.js index 9ad491d2..11f1313d 100644 --- a/client/src/components/termsPrompt/index.tsx +++ b/client/src/components/termsPrompt/index.js @@ -10,25 +10,13 @@ import { } from "@blueprintjs/core"; import { storageGet, storageSet, KEYS } from "../util/localStorage"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -type State = any; - -// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message @connect((state) => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - tosURL: (state as any).config?.parameters?.about_legal_tos, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - privacyURL: (state as any).config?.parameters?.about_legal_privacy, + tosURL: state.config?.parameters?.about_legal_tos, + privacyURL: state.config?.parameters?.about_legal_privacy, })) -// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. -class TermsPrompt extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - drawerClose: any; - - // eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS. - constructor(props: {}) { +class TermsPrompt extends React.PureComponent { + constructor(props) { super(props); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message const { tosURL, privacyURL } = this.props; const cookieDecision = storageGet(KEYS.COOKIE_DECISION, null); const hasDecided = cookieDecision !== null; @@ -39,7 +27,6 @@ class TermsPrompt extends React.PureComponent<{}, State> { }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. componentDidMount() { const { hasDecided, isEnabled } = this.state; if (isEnabled && !hasDecided) { @@ -47,14 +34,11 @@ class TermsPrompt extends React.PureComponent<{}, State> { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleOK = () => { this.setState({ isOpen: false }); storageSet(KEYS.COOKIE_DECISION, "yes"); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'cookieDecisionCallback' does not exist o... Remove this comment to see the full error message if (window.cookieDecisionCallback instanceof Function) { try { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'cookieDecisionCallback' does not exist o... Remove this comment to see the full error message window.cookieDecisionCallback(); } catch (e) { // continue @@ -62,15 +46,12 @@ class TermsPrompt extends React.PureComponent<{}, State> { } }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. handleNo = () => { this.setState({ isOpen: false }); storageSet(KEYS.COOKIE_DECISION, "no"); }; - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderTos() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'tosURL' does not exist on type 'Readonly... Remove this comment to see the full error message const { tosURL } = this.props; if (!tosURL) return null; return ( @@ -93,9 +74,7 @@ class TermsPrompt extends React.PureComponent<{}, State> { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. renderPrivacy() { - // @ts-expect-error ts-migrate(2339) FIXME: Property 'privacyURL' does not exist on type 'Read... Remove this comment to see the full error message const { privacyURL } = this.props; if (!privacyURL) return null; return ( @@ -117,22 +96,18 @@ class TermsPrompt extends React.PureComponent<{}, State> { ); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. render() { const { isOpen, isEnabled } = this.state; if (!isEnabled || !isOpen) return null; return ( @@ -168,4 +143,5 @@ class TermsPrompt extends React.PureComponent<{}, State> { ); } } + export default TermsPrompt; diff --git a/client/src/components/util/localStorage.js b/client/src/components/util/localStorage.js new file mode 100644 index 00000000..5766d9f9 --- /dev/null +++ b/client/src/components/util/localStorage.js @@ -0,0 +1,22 @@ +export const KEYS = { + COOKIE_DECISION: "cxg.cookieDecision", + LOGIN_PROMPT: "cxg.LOGIN_PROMPT", +}; + +export function storageGet(key, defaultValue = null) { + try { + const val = window.localStorage.getItem(key); + if (val === null) return defaultValue; + return val; + } catch (e) { + return defaultValue; + } +} + +export function storageSet(key, value) { + try { + window.localStorage.setItem(key, value); + } catch { + // continue + } +} diff --git a/client/src/components/util/localStorage.ts b/client/src/components/util/localStorage.ts deleted file mode 100644 index 8f411fc0..00000000 --- a/client/src/components/util/localStorage.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const KEYS = { - COOKIE_DECISION: "cxg.cookieDecision", - LOGIN_PROMPT: "cxg.LOGIN_PROMPT", -}; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function storageGet(key: any, defaultValue = null) { - try { - const val = window.localStorage.getItem(key); - if (val === null) return defaultValue; - return val; - } catch (e) { - return defaultValue; - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function storageSet(key: any, value: any) { - try { - window.localStorage.setItem(key, value); - } catch { - // continue - } -} diff --git a/client/src/components/util/truncate.tsx b/client/src/components/util/truncate.js similarity index 80% rename from client/src/components/util/truncate.tsx rename to client/src/components/util/truncate.js index 09b80952..ba5c5d55 100644 --- a/client/src/components/util/truncate.tsx +++ b/client/src/components/util/truncate.js @@ -32,8 +32,7 @@ const SECOND_HALF_INNER_STYLE = { right: 0, }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export default (props: any) => { +export default (props) => { const { children, isGenesetDescription, tooltipAddendum = "" } = props; // Truncate only support a single child with a text child @@ -71,12 +70,9 @@ export default (props: any) => { const truncatedJSX = ( - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ overflow: string; textOverflow: string; wh... Remove this comment to see the full error message */} {firstString} - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ position: string; overflow: string; whiteS... Remove this comment to see the full error message */} {secondString} - {/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ color: any; position: string; right: numbe... Remove this comment to see the full error message */} {secondString} @@ -106,7 +102,6 @@ export default (props: any) => { : `${originalString}${tooltipAddendum}` } hoverOpenDelay={tooltipHoverOpenDelayQuick} - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. targetProps={{ style: children.props.style }} > {newChildren} diff --git a/client/src/globals.ts b/client/src/globals.js similarity index 84% rename from client/src/globals.ts rename to client/src/globals.js index 5db99238..ec1ee269 100644 --- a/client/src/globals.ts +++ b/client/src/globals.js @@ -8,24 +8,11 @@ export const overflowCategoryLabel = ": all other labels"; /* default "unassigned" value for user-created categorical metadata */ export const unassignedCategoryLabel = "unassigned"; -/* rough shape of config object */ -export interface Config { - features: Record; - displayNames: Record; - parameters: { - "disable-diffexp"?: boolean; - "diffexp-may-be-slow"?: boolean; - default_embedding?: string; - [key: string]: unknown; - }; - links: Record; -} - /* these are default values for configuration the CLI may supply. See the REST API and CLI specs for more info. */ -export const configDefaults: Config = { +export const configDefaults = { features: {}, displayNames: {}, parameters: { @@ -39,7 +26,6 @@ export const configDefaults: Config = { Most configuration is stored in the reducer. A handful of values are global and stored here. They are typically set by the config action handler, which pull the information from the backend/CLI. - All should be set here to their default value. */ export const globalConfig = { @@ -116,10 +102,8 @@ const CXG_SERVER_PORT = let _API; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -if ((window as any).CELLXGENE && (window as any).CELLXGENE.API) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - _API = (window as any).CELLXGENE.API; +if (window.CELLXGENE && window.CELLXGENE.API) { + _API = window.CELLXGENE.API; } else { if (CXG_SERVER_PORT === undefined) { const errorMessage = "Please set the CXG_SERVER_PORT environment variable."; diff --git a/client/src/index.tsx b/client/src/index.js similarity index 100% rename from client/src/index.tsx rename to client/src/index.js diff --git a/client/src/reducers/annoMatrix.js b/client/src/reducers/annoMatrix.js new file mode 100644 index 00000000..830e1834 --- /dev/null +++ b/client/src/reducers/annoMatrix.js @@ -0,0 +1,12 @@ +/* +Reducer for the annoMatrix +*/ + +const AnnoMatrix = (state = null, action) => { + if (action.annoMatrix) { + return action.annoMatrix; + } + return state; +}; + +export default AnnoMatrix; diff --git a/client/src/reducers/annoMatrix.ts b/client/src/reducers/annoMatrix.ts deleted file mode 100644 index 82e30228..00000000 --- a/client/src/reducers/annoMatrix.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* -Reducer for the annoMatrix -*/ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const AnnoMatrix = (state = null, action: any) => { - if (action.annoMatrix) { - return action.annoMatrix; - } - return state; -}; - -export default AnnoMatrix; diff --git a/client/src/reducers/annotations.ts b/client/src/reducers/annotations.js similarity index 91% rename from client/src/reducers/annotations.ts rename to client/src/reducers/annotations.js index b2282c91..5178d0cf 100644 --- a/client/src/reducers/annotations.ts +++ b/client/src/reducers/annotations.js @@ -1,7 +1,6 @@ /* Reducers for annotation UI-state. */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Annotations = ( state = { /* @@ -29,8 +28,7 @@ const Annotations = ( labelEditable: { category: null, label: null }, promptForFilename: true, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { case "configuration load complete": { diff --git a/client/src/reducers/autosave.ts b/client/src/reducers/autosave.js similarity index 78% rename from client/src/reducers/autosave.ts rename to client/src/reducers/autosave.js index 6b4611a2..26d67387 100644 --- a/client/src/reducers/autosave.ts +++ b/client/src/reducers/autosave.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Autosave = ( state = { // cell labels @@ -12,10 +11,8 @@ const Autosave = ( // error state error: false, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - nextSharedState: any + action, + nextSharedState ) => { switch (action.type) { case "annoMatrix: init complete": { diff --git a/client/src/reducers/cascade.ts b/client/src/reducers/cascade.js similarity index 74% rename from client/src/reducers/cascade.ts rename to client/src/reducers/cascade.js index 046c6520..3c023f67 100644 --- a/client/src/reducers/cascade.ts +++ b/client/src/reducers/cascade.js @@ -1,5 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export default function cascadeReducers(arg: any) { +export default function cascadeReducers(arg) { /* Combine a set of cascading reducers into a single reducer. Cascading reducers are reducers which may rely on state computed by another reducer. @@ -24,8 +23,7 @@ export default function cascadeReducers(arg: any) { */ const reducers = arg instanceof Map ? arg : new Map(arg); const reducerKeys = [...reducers.keys()]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - return (prevState: any, action: any) => { + return (prevState, action) => { const nextState = {}; let stateChange = false; for (let i = 0, l = reducerKeys.length; i < l; i += 1) { @@ -38,7 +36,6 @@ export default function cascadeReducers(arg: any) { nextState, prevState ); - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message nextState[key] = nextStateForKey; stateChange = stateChange || nextStateForKey !== prevStateForKey; } diff --git a/client/src/reducers/categoricalSelection.ts b/client/src/reducers/categoricalSelection.js similarity index 72% rename from client/src/reducers/categoricalSelection.ts rename to client/src/reducers/categoricalSelection.js index 791a126a..d1080699 100644 --- a/client/src/reducers/categoricalSelection.ts +++ b/client/src/reducers/categoricalSelection.js @@ -11,15 +11,7 @@ Label state default (if missing) is up to the component, but typically true. ... } */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -const CategoricalSelection = ( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - state: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - nextSharedState: any -) => { +const CategoricalSelection = (state, action, nextSharedState) => { switch (action.type) { case "initial data load complete": case "subset to selection": @@ -27,7 +19,6 @@ const CategoricalSelection = ( case "set clip quantiles": { const { annoMatrix } = nextSharedState; const newState = CH.createCategoricalSelection( - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. CH.selectableCategoryNames(annoMatrix.schema) ); return newState; diff --git a/client/src/reducers/centroidLabels.ts b/client/src/reducers/centroidLabels.js similarity index 53% rename from client/src/reducers/centroidLabels.ts rename to client/src/reducers/centroidLabels.js index af2703b9..6481ec1d 100644 --- a/client/src/reducers/centroidLabels.ts +++ b/client/src/reducers/centroidLabels.js @@ -2,14 +2,7 @@ const initialState = { showLabels: false, }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -const centroidLabels = ( - state = initialState, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - sharedNextState: any -) => { +const centroidLabels = (state = initialState, action, sharedNextState) => { const { colors: { colorAccessor }, } = sharedNextState; diff --git a/client/src/reducers/colors.ts b/client/src/reducers/colors.js similarity index 88% rename from client/src/reducers/colors.ts rename to client/src/reducers/colors.js index 0553774e..a9afdecc 100644 --- a/client/src/reducers/colors.ts +++ b/client/src/reducers/colors.js @@ -2,14 +2,12 @@ Color By UI state */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const ColorsReducer = ( state = { colorMode: null /* by continuous, by expression */, colorAccessor: null /* tissue, Apod */, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { case "universe: user color load success": { diff --git a/client/src/reducers/config.ts b/client/src/reducers/config.js similarity index 65% rename from client/src/reducers/config.ts rename to client/src/reducers/config.js index a5a57e26..22858c8f 100644 --- a/client/src/reducers/config.ts +++ b/client/src/reducers/config.js @@ -1,12 +1,10 @@ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Config = ( state = { displayNames: null, features: null, parameters: null, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { case "initial data load start": diff --git a/client/src/reducers/continuousSelection.ts b/client/src/reducers/continuousSelection.js similarity index 64% rename from client/src/reducers/continuousSelection.ts rename to client/src/reducers/continuousSelection.js index 8923c2b6..2060d3bf 100644 --- a/client/src/reducers/continuousSelection.ts +++ b/client/src/reducers/continuousSelection.js @@ -1,23 +1,6 @@ -import type { Action } from "redux"; - import { makeContinuousDimensionName } from "../util/nameCreators"; -import type { ContinuousNamespace } from "../util/nameCreators"; - -export interface ContinuousSelectionAction extends Action { - continuousNamespace: ContinuousNamespace; - selection: string; - range: [number, number]; -} - -export interface ContinuousSelectionState { - [name: string]: [number, number]; -} - -const ContinuousSelection = ( - state: ContinuousSelectionState = {}, - action: ContinuousSelectionAction -): ContinuousSelectionState => { +const ContinuousSelection = (state = {}, action) => { switch (action.type) { case "reset subset": case "subset to selection": diff --git a/client/src/reducers/controls.ts b/client/src/reducers/controls.js similarity index 92% rename from client/src/reducers/controls.ts rename to client/src/reducers/controls.js index f94f5d56..e9232030 100644 --- a/client/src/reducers/controls.ts +++ b/client/src/reducers/controls.js @@ -1,7 +1,6 @@ import uniq from "lodash.uniq"; import filter from "lodash.filter"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Controls = ( state = { // data loading flag @@ -21,8 +20,7 @@ const Controls = ( datasetDrawer: false, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { /* For now, log anything looking like an error to the console. diff --git a/client/src/reducers/differential.ts b/client/src/reducers/differential.js similarity index 77% rename from client/src/reducers/differential.ts rename to client/src/reducers/differential.js index 6cab67ba..6401cce7 100644 --- a/client/src/reducers/differential.ts +++ b/client/src/reducers/differential.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const Differential = ( state = { loading: null, @@ -6,8 +5,7 @@ const Differential = ( celllist1: null, celllist2: null, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { case "request differential expression started": diff --git a/client/src/reducers/genesets.ts b/client/src/reducers/genesets.js similarity index 92% rename from client/src/reducers/genesets.ts rename to client/src/reducers/genesets.js index d91f5c8c..94356ce9 100644 --- a/client/src/reducers/genesets.ts +++ b/client/src/reducers/genesets.js @@ -24,15 +24,13 @@ */ import { diffexpPopNamePrefix1, diffexpPopNamePrefix2 } from "../globals"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const GeneSets = ( state = { initialized: false, lastTid: undefined, genesets: new Map(), }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { /** @@ -355,7 +353,6 @@ const GeneSets = ( const { tid } = action; if (!Number.isInteger(tid) || tid < 0) throw new Error("TID must be a positive integer number"); - // @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'. if (state.lastTid !== undefined && tid < state.lastTid) throw new Error("TID may not be decremented."); return { @@ -377,8 +374,7 @@ const GeneSets = ( const diffExpGeneSets = []; for (const polarity of Object.keys(genesetNames)) { const genes = new Map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - data[polarity].map((diffExpGene: any) => [ + data[polarity].map((diffExpGene) => [ diffExpGene[0], { geneSymbol: diffExpGene[0], @@ -386,10 +382,8 @@ const GeneSets = ( ]) ); diffExpGeneSets.push([ - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message genesetNames[polarity], { - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message genesetName: genesetNames[polarity], genesetDescription: "", genes, @@ -397,7 +391,6 @@ const GeneSets = ( ]); } - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. const genesets = new Map([...diffExpGeneSets, ...state.genesets]); // clone return { diff --git a/client/src/reducers/genesetsUI.ts b/client/src/reducers/genesetsUI.js similarity index 87% rename from client/src/reducers/genesetsUI.ts rename to client/src/reducers/genesetsUI.js index 6a11a7c1..a49aa9b9 100644 --- a/client/src/reducers/genesetsUI.ts +++ b/client/src/reducers/genesetsUI.js @@ -1,15 +1,13 @@ /* Reducers for geneset UI-state. */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const GeneSetsUI = ( state = { createGenesetModeActive: false, isEditingGenesetName: false, isAddingGenesToGeneset: false, }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { /** diff --git a/client/src/reducers/graphSelection.ts b/client/src/reducers/graphSelection.js similarity index 79% rename from client/src/reducers/graphSelection.ts rename to client/src/reducers/graphSelection.js index 8145aae4..15589462 100644 --- a/client/src/reducers/graphSelection.ts +++ b/client/src/reducers/graphSelection.js @@ -1,11 +1,9 @@ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const GraphSelection = ( state = { tool: "lasso", // what selection tool mode (lasso, brush, ...) selection: { mode: "all" }, // current selection, which is tool specific }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any + action ) => { switch (action.type) { case "set clip quantiles": diff --git a/client/src/reducers/index.ts b/client/src/reducers/index.js similarity index 88% rename from client/src/reducers/index.ts rename to client/src/reducers/index.js index 633de304..8f07bfe4 100644 --- a/client/src/reducers/index.ts +++ b/client/src/reducers/index.js @@ -1,5 +1,5 @@ -import { createStore, applyMiddleware, AnyAction } from "redux"; -import thunk, { ThunkDispatch } from "redux-thunk"; +import { createStore, applyMiddleware } from "redux"; +import thunk from "redux-thunk"; import cascadeReducers from "./cascade"; import undoable from "./undoable"; @@ -63,8 +63,4 @@ const Reducer = undoable( const store = createStore(Reducer, applyMiddleware(thunk, annoMatrixGC)); -export type RootState = ReturnType; - -export type AppDispatch = ThunkDispatch; - export default store; diff --git a/client/src/reducers/layoutChoice.ts b/client/src/reducers/layoutChoice.js similarity index 57% rename from client/src/reducers/layoutChoice.ts rename to client/src/reducers/layoutChoice.js index 1e36b32d..d1080f2c 100644 --- a/client/src/reducers/layoutChoice.ts +++ b/client/src/reducers/layoutChoice.js @@ -7,34 +7,28 @@ about commonly used names. Preferentially, pick in the following order: 3. "pca" 4. give up, use the first available */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function bestDefaultLayout(layouts: any) { +function bestDefaultLayout(layouts) { const preferredNames = ["umap", "tsne", "pca"]; const idx = preferredNames.findIndex((name) => layouts.indexOf(name) !== -1); if (idx !== -1) return preferredNames[idx]; return layouts[0]; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function setToDefaultLayout(schema: any) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const available = schema.layout.obs.map((v: any) => v.name).sort(); +function setToDefaultLayout(schema) { + const available = schema.layout.obs.map((v) => v.name).sort(); const current = bestDefaultLayout(available); const currentDimNames = schema.layout.obsByName[current].dims; return { available, current, currentDimNames }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const LayoutChoice = ( state = { available: [], // all available choices current: undefined, // name of the current layout, eg, 'umap' currentDimNames: [], // dimension name }, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - action: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - nextSharedState: any + action, + nextSharedState ) => { switch (action.type) { case "initial data load complete": { diff --git a/client/src/reducers/obsCrossfilter.js b/client/src/reducers/obsCrossfilter.js new file mode 100644 index 00000000..5fc2199a --- /dev/null +++ b/client/src/reducers/obsCrossfilter.js @@ -0,0 +1,12 @@ +/* +Reducer for the obsCrossfilter +*/ + +const ObsCrossfilter = (state = null, action) => { + if (action.obsCrossfilter) { + return action.obsCrossfilter; + } + return state; +}; + +export default ObsCrossfilter; diff --git a/client/src/reducers/obsCrossfilter.ts b/client/src/reducers/obsCrossfilter.ts deleted file mode 100644 index 7c38652d..00000000 --- a/client/src/reducers/obsCrossfilter.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* -Reducer for the obsCrossfilter -*/ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const ObsCrossfilter = (state = null, action: any) => { - if (action.obsCrossfilter) { - return action.obsCrossfilter; - } - return state; -}; - -export default ObsCrossfilter; diff --git a/client/src/reducers/pointDilation.ts b/client/src/reducers/pointDilation.js similarity index 71% rename from client/src/reducers/pointDilation.ts rename to client/src/reducers/pointDilation.js index 8c0ed83f..f8155545 100644 --- a/client/src/reducers/pointDilation.ts +++ b/client/src/reducers/pointDilation.js @@ -3,8 +3,7 @@ const initialState = { categoryField: "", }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -const pointDialation = (state = initialState, action: any) => { +const pointDialation = (state = initialState, action) => { const { metadataField, label: categoryField } = action; switch (action.type) { diff --git a/client/src/reducers/undoable.ts b/client/src/reducers/undoable.js similarity index 73% rename from client/src/reducers/undoable.ts rename to client/src/reducers/undoable.js index 225b958e..d18d0f4b 100644 --- a/client/src/reducers/undoable.ts +++ b/client/src/reducers/undoable.js @@ -51,55 +51,23 @@ history state processing. The undoable action object contents, by key: filter state are entirely at the discretion of the action filter. */ -import { Reducer, AnyAction } from "redux"; import fromEntries from "../util/fromEntries"; -export const pastKey = "@@undoable/past"; -export const futureKey = "@@undoable/future"; -export const filterStateKey = "@@undoable/filterState"; -export const filterActionKey = "@@undoable/filterAction"; -export const pendingKey = "@@undoable/pending"; +const historyKeyPrefix = "@@undoable/"; +const pastKey = `${historyKeyPrefix}past`; +const futureKey = `${historyKeyPrefix}future`; +const filterStateKey = `${historyKeyPrefix}filterState`; +const filterActionKey = `${historyKeyPrefix}filterAction`; +const pendingKey = `${historyKeyPrefix}pending`; const defaultHistoryLimit = -100; -export interface UndoableFilterState { - [name: string]: unknown; -} - -export interface UndoableConfig { - debug?: boolean | number; - historyLimit?: number; - actionFilter?: ActionFilterFn; -} - -export interface UndoableAction { - [filterActionKey]: string; - [filterStateKey]?: FilterStateType; -} - -export type ActionFilterFn = ( - undoableState: UndoableState, - action: AnyAction, - filterState?: FilterStateType -) => UndoableAction; - -export interface UndoableState { - [pastKey]: [string, unknown][][]; - [futureKey]: [string, unknown][][]; - [pendingKey]: [string, unknown][] | null; - [filterStateKey]: FilterStateType | undefined; -} - -const Undoable = ( - reducer: Reducer, - undoableKeys: string[], - options: UndoableConfig = {} -): Reducer => { - const debug = options?.debug ?? false; +const Undoable = (reducer, undoableKeys, options = {}) => { + const { debug } = options; let { historyLimit } = options; if (!historyLimit) historyLimit = defaultHistoryLimit; if (historyLimit > 0) historyLimit = -historyLimit; - const actionFilter: ActionFilterFn = - options?.actionFilter ?? (() => ({ [filterActionKey]: "save" })); + const actionFilter = + options.actionFilter || (() => ({ [filterActionKey]: "save" })); if (!Array.isArray(undoableKeys) || undoableKeys.length === 0) throw new Error("undoable keys array must be specified"); @@ -108,9 +76,7 @@ const Undoable = ( /* Undo the current to previous history */ - function undo( - currentState: UndoableState - ): UndoableState { + function undo(currentState) { const past = currentState[pastKey]; const future = currentState[futureKey]; if (past.length === 0) return currentState; @@ -118,7 +84,7 @@ const Undoable = ( undoableKeysSet.has(kv[0]) ); const newPast = [...past]; - const newState = newPast.pop() || []; + const newState = newPast.pop(); const newFuture = push(future, currentUndoableState); const nextState = { ...currentState, @@ -133,9 +99,7 @@ const Undoable = ( /* Replay future, previously undone. */ - function redo( - currentState: UndoableState - ): UndoableState { + function redo(currentState) { const past = currentState[pastKey] || []; const future = currentState[futureKey] || []; if (future.length === 0) return currentState; @@ -143,7 +107,7 @@ const Undoable = ( undoableKeysSet.has(kv[0]) ); const newFuture = [...future]; - const newState = newFuture.pop() || []; + const newState = newFuture.pop(); const newPast = push(past, currentUndoableState); const nextState = { ...currentState, @@ -158,14 +122,12 @@ const Undoable = ( /* Clear the history state. No side-effects on current state. */ - function clear( - currentState: UndoableState - ): UndoableState { + function clear(currentState) { return { ...currentState, [pastKey]: [], [futureKey]: [], - [filterStateKey]: undefined, + [filterStateKey]: {}, [pendingKey]: null, }; } @@ -173,11 +135,7 @@ const Undoable = ( /* Reduce current action, with no history side-effects */ - function skip( - currentState: UndoableState, - action: AnyAction, - filterState: UndoableFilterState - ): UndoableState { + function skip(currentState, action, filterState) { const past = currentState[pastKey] || []; const future = currentState[futureKey] || []; const pending = currentState[pendingKey]; @@ -194,11 +152,7 @@ const Undoable = ( /* Save current state in the history, then reduce action. */ - function save( - currentState: UndoableState, - action: AnyAction, - filterState: UndoableFilterState - ): UndoableState { + function save(currentState, action, filterState) { const past = currentState[pastKey] || []; const currentUndoableState = Object.entries(currentState).filter((kv) => undoableKeysSet.has(kv[0]) @@ -218,9 +172,7 @@ const Undoable = ( /* Save current state as pending history change. No other side effects. */ - function stashPending( - currentState: UndoableState - ): UndoableState { + function stashPending(currentState) { const currentUndoableState = Object.entries(currentState).filter((kv) => undoableKeysSet.has(kv[0]) ); @@ -233,9 +185,7 @@ const Undoable = ( /* Cancel pending history state change. No other side effects. */ - function cancelPending( - currentState: UndoableState - ): UndoableState { + function cancelPending(currentState) { return { ...currentState, [pendingKey]: null, @@ -245,12 +195,9 @@ const Undoable = ( /* Push pending state onto the history stack */ - function applyPending( - currentState: UndoableState - ): UndoableState { - const past = currentState[pastKey]; + function applyPending(currentState) { + const past = currentState[pastKey] || []; const pendingState = currentState[pendingKey]; - if (pendingState === null) return currentState; const newPast = push(past, pendingState, historyLimit); const nextState = { ...currentState, @@ -262,13 +209,13 @@ const Undoable = ( } return ( - currentState: UndoableState = { + currentState = { [pastKey]: [], [futureKey]: [], - [filterStateKey]: undefined, + [filterStateKey]: {}, [pendingKey]: null, }, - action: AnyAction + action ) => { if (debug > 1) console.log("---- ACTION", action.type); const aType = action.type; @@ -328,7 +275,7 @@ const Undoable = ( }; }; -function push(arr: T[], val: T, limit?: number) { +function push(arr, val, limit = undefined) { /* functional array push, with a max length limit to the new array. Like Array.push, except it returns new array and discards as needed diff --git a/client/src/reducers/undoableConfig.ts b/client/src/reducers/undoableConfig.js similarity index 63% rename from client/src/reducers/undoableConfig.ts rename to client/src/reducers/undoableConfig.js index df0ef1f5..d18270ad 100644 --- a/client/src/reducers/undoableConfig.ts +++ b/client/src/reducers/undoableConfig.js @@ -1,19 +1,13 @@ -import { AnyAction } from "redux"; -import { StateMachine, FsmActionFn, FsmErrorFn } from "../util/statemachine"; -import { - UndoableConfig, - UndoableState, - UndoableFilterState, - UndoableAction, - filterActionKey, - filterStateKey, -} from "./undoable"; +import StateMachine from "../util/statemachine"; import createFsmTransitions from "./undoableFsm"; +const actionKey = "@@undoable/filterAction"; +const stateKey = "@@undoable/filterState"; + /* these actions will not affect history */ -const skipOnActions = new Set([ +const skipOnActions = new Set([ "annoMatrix: init complete", "url changed", "initial data load start", @@ -64,12 +58,12 @@ const skipOnActions = new Set([ identical, repeated occurances of these action types will be debounced. Entire action must be identical (all keys). */ -const debounceOnActions = new Set([]); +const debounceOnActions = new Set([]); /* history will be cleared when these actions occur */ -const clearOnActions = new Set([ +const clearOnActions = new Set([ "initial data load complete", "initial data load error", ]); @@ -77,7 +71,7 @@ const clearOnActions = new Set([ /* An immediate history save will be done for these */ -const saveOnActions = new Set([ +const saveOnActions = new Set([ "categorical metadata filter select", "categorical metadata filter deselect", "categorical metadata filter all of these", @@ -125,43 +119,32 @@ StateMachine - processing complex action handling - see FSM graph for actual structure, in undoableFsm.js **/ -interface MyFilterState extends UndoableFilterState { - prevAction?: AnyAction; - fsm: StateMachine | null; -} -type MyUndoableAction = UndoableAction; - /* Default FSM actions. Used to side-effect transitions in the graph. See graph definition for the transitions that use each. Signature: (fsm, transition, reducerState, reducerAction) => undoableAction */ -const stashPending: FsmActionFn = ( - fsm: StateMachine -) => ({ - [filterActionKey]: "stashPending", - [filterStateKey]: { fsm }, +const stashPending = (fsm) => ({ + [actionKey]: "stashPending", + [stateKey]: { fsm }, }); -const cancelPending: FsmActionFn = () => ({ - [filterActionKey]: "cancelPending", - [filterStateKey]: { fsm: null }, +const cancelPending = () => ({ + [actionKey]: "cancelPending", + [stateKey]: { fsm: null }, }); -const applyPending: FsmActionFn = () => ({ - [filterActionKey]: "applyPending", - [filterStateKey]: { fsm: null }, +const applyPending = () => ({ + [actionKey]: "applyPending", + [stateKey]: { fsm: null }, }); -const skip: FsmActionFn = (fsm, transition) => ({ - [filterActionKey]: "skip", - [filterStateKey]: { fsm: transition.to !== "done" ? fsm : null }, +const skip = (fsm, transition) => ({ + [actionKey]: "skip", + [stateKey]: { fsm: transition.to !== "done" ? fsm : null }, }); -const clear: FsmActionFn = () => ({ - [filterActionKey]: "clear", - [filterStateKey]: { fsm: null }, -}); -const save: FsmActionFn = (fsm, transition) => ({ - [filterActionKey]: "save", - [filterStateKey]: { fsm: transition.to !== "done" ? fsm : null }, +const clear = () => ({ [actionKey]: "clear", [stateKey]: { fsm: null } }); +const save = (fsm, transition) => ({ + [actionKey]: "save", + [stateKey]: { fsm: transition.to !== "done" ? fsm : null }, }); /* @@ -170,13 +153,10 @@ StateMachine when it doesn't know what to do. Signature: (fsm, event, from) => undoableAction */ -const onFsmError: FsmErrorFn = (fsm, event, from) => { +const onFsmError = (fsm, event, from) => { console.error(`FSM error [event: "${event}", state: "${from}"]`, fsm); // In production, try to recover gracefully if we have unexpected state - return { - [filterActionKey]: "clear", - [filterStateKey]: { fsm: null }, - }; + return clear(); }; /* @@ -191,11 +171,7 @@ const fsmTransitions = createFsmTransitions( save ); /* State machine we clone whenever we need to run it */ -const seedFsm = new StateMachine( - "init", - fsmTransitions, - onFsmError -); +const seedFsm = new StateMachine("init", fsmTransitions, onFsmError); /* See undoable.js for description action filter interface description. @@ -205,52 +181,44 @@ Basic approach: * only implement complex state machines where absolutely required (eg, multi-event selection and the like) */ -const actionFilter = - (debug: boolean) => - ( - state: UndoableState, - action: AnyAction, - prevFilterState: MyFilterState | undefined - ): UndoableAction => { - const actionType = action.type; - prevFilterState = prevFilterState || { fsm: null }; - const filterState: MyFilterState = { - ...prevFilterState, - prevAction: action, - }; - if (skipOnActions.has(actionType)) { - return { [filterActionKey]: "skip", [filterStateKey]: filterState }; - } - if ( - debounceOnActions.has(actionType) && - prevFilterState.prevAction && - shallowObjectEq(action, prevFilterState.prevAction) - ) { - return { [filterActionKey]: "skip", [filterStateKey]: filterState }; - } - if (clearOnActions.has(actionType)) { - return { [filterActionKey]: "clear", [filterStateKey]: filterState }; - } - if (saveOnActions.has(actionType)) { - return { [filterActionKey]: "save", [filterStateKey]: filterState }; - } +const actionFilter = (debug) => (state, action, prevFilterState) => { + const actionType = action.type; + const filterState = { + ...prevFilterState, + prevAction: action, + }; + if (skipOnActions.has(actionType)) { + return { [actionKey]: "skip", [stateKey]: filterState }; + } + if ( + debounceOnActions.has(actionType) && + shallowObjectEq(action, prevFilterState.prevAction) + ) { + return { [actionKey]: "skip", [stateKey]: filterState }; + } + if (clearOnActions.has(actionType)) { + return { [actionKey]: "clear", [stateKey]: filterState }; + } + if (saveOnActions.has(actionType)) { + return { [actionKey]: "save", [stateKey]: filterState }; + } - /* + /* Else, something more complex OR unknown to us.... */ - if (seedFsm.events.has(actionType)) { - let { fsm } = filterState; - if (!fsm) { - /* no active FSM, so create one in init state */ - fsm = seedFsm.clone("init"); - } - return fsm.next(action.type, { state, action }); + if (seedFsm.events.has(actionType)) { + let { fsm } = filterState; + if (!fsm) { + /* no active FSM, so create one in init state */ + fsm = seedFsm.clone("init"); } + return fsm.next(action.type, { state, action }); + } - /* else, we have no idea what this is - skip it */ - if (debug) console.log("**** ACTION FILTER EVENT HANDLER MISS", actionType); - return { [filterActionKey]: "skip", [filterStateKey]: filterState }; - }; + /* else, we have no idea what this is - skip it */ + if (debug) console.log("**** ACTION FILTER EVENT HANDLER MISS", actionType); + return { [actionKey]: "skip", [stateKey]: filterState }; +}; /* return true if objA and objB are ===, OR if: @@ -258,10 +226,7 @@ return true if objA and objB are ===, OR if: - have same own properties - all values are strict equal (===) */ -function shallowObjectEq( - objA: Record, - objB: Record -) { +function shallowObjectEq(objA, objB) { if (objA === objB) return true; if (!objA || !objB) return false; if (!shallowArrayEq(Object.keys(objA), Object.keys(objB))) return false; @@ -273,7 +238,7 @@ function shallowObjectEq( return true if arrA and arrB contain the same strict-equal values, in the same order. */ -function shallowArrayEq(arrA: unknown[], arrB: unknown[]) { +function shallowArrayEq(arrA, arrB) { if (arrA.length !== arrB.length) return false; for (let i = 0, l = arrA.length; i < l; i += 1) { if (arrA[i] !== arrB[i]) return false; @@ -288,7 +253,7 @@ Set to true or 1 for base logging, high number for more verbosity (currently onl or 2). */ const debug = false; -const undoableConfig: UndoableConfig = { +const undoableConfig = { debug, historyLimit: 50, // maximum history size actionFilter: actionFilter(debug), @@ -327,7 +292,7 @@ if (debug) { ); if (trivialOverlapWithFsm.size > 0) { console.error( - "Undoable misconfiguration - trivial action filter blocking FSM filter", + "Undoable misconfiguration - trivival action filter blocking FSM filter", [...trivialOverlapWithFsm] ); } diff --git a/client/src/reducers/undoableFsm.js b/client/src/reducers/undoableFsm.js new file mode 100644 index 00000000..4a66e9ae --- /dev/null +++ b/client/src/reducers/undoableFsm.js @@ -0,0 +1,196 @@ +/* +State transition graph for complex action/history interactions. + +Assumed configuration from undoableConfig: + * By convention, "init" is used as the start state for all, and "done" + as the final state. + * Unexpected states will result in an error, plus a clear and cancelPending + side-effect. + +TODO: is is possible there is a more concise format for this, as it is +a fairly repetitive pattern. + +These events are largely one of two types: +a) async operations or multi-event options that should only be committed +upon some success criteria, otherwise cancelled. + +b) compound actions that should be collapsed into a single history change. + +*/ + +const createFsmTransitions = ( + stashPending, + cancelPending, + applyPending, + skip, + clear, + save +) => [ + /* graph selection brushing */ + { + event: "graph brush start", + from: "init", + to: "graph brush in progress", + action: stashPending, + }, + { + event: "graph brush cancel", + from: "graph brush in progress", + to: "done", + action: applyPending, + }, + { + event: "graph brush deselect", + from: "graph brush in progress", + to: "done", + /* if current selection is all, cancelPending. Else, applyPending */ + action: (fsm, transition, data) => + data.state.graphSelection.selection.mode === "all" + ? cancelPending() + : applyPending(), + }, + { + event: "graph brush end", + from: "graph brush in progress", + to: "done", + action: applyPending, + }, + + /* graph selection lasso */ + { + event: "graph lasso start", + from: "init", + to: "graph lasso in progress", + action: stashPending, + }, + { + event: "graph lasso cancel", + from: "graph lasso in progress", + to: "done", + action: applyPending, + }, + { + event: "graph lasso deselect", + from: "graph lasso in progress", + to: "done", + /* if current selection is all, cancelPending. Else, applyPending */ + action: (fsm, transition, data) => + data.state.graphSelection.selection.mode === "all" + ? cancelPending() + : applyPending(), + }, + { + event: "graph lasso end", + from: "graph lasso in progress", + to: "done", + action: applyPending, + }, + + /* Continuous metadata histogram brush selection */ + { + event: "continuous metadata histogram start", + from: "init", + to: "continuous histo select in progress", + action: stashPending, + }, + { + event: "continuous metadata histogram cancel", + from: "continuous histo select in progress", + to: "done", + action: cancelPending, + }, + { + event: "continuous metadata histogram cancel", + from: "init", + to: "done", + action: save, + }, + { + event: "continuous metadata histogram end", + from: "continuous histo select in progress", + to: "done", + action: applyPending, + }, + + /* Single gene request by user */ + { + event: "single user defined gene start", + from: "init", + to: "single user gene request in progress", + action: stashPending, + }, + { + event: "request user defined gene error", + from: "single user gene request in progress", + to: "single user gene error in progress", + action: skip, + }, + { + event: "single user defined gene error", + from: "single user gene error in progress", + to: "done", + action: cancelPending, + }, + { + event: "single user defined gene complete", + from: "single user gene request in progress", + to: "done", + action: applyPending, + }, + + /* Bulk gene request by user */ + { + event: "bulk user defined gene start", + from: "init", + to: "bulk user gene request in progress", + action: stashPending, + }, + { + event: "request user defined gene error", + from: "bulk user gene request in progress", + to: "bulk user gene request error in progress", + action: skip, + }, + { + event: "bulk user defined gene error", + from: "bulk user gene request error in progress", + to: "done", + action: cancelPending, + }, + { + event: "bulk user defined gene complete", + from: "bulk user gene request in progress", + to: "done", + action: applyPending, + }, + + /* Compute Differential Expression button user action */ + { + event: "request differential expression started", + from: "init", + to: "diffexp in progress", + action: stashPending, + }, + { + event: "request user defined gene error", + from: "diffexp in progress", + to: "done", + action: cancelPending, + }, + { + event: "request differential expression success", + from: "diffexp in progress", + to: "done", + action: applyPending, + }, + + /* clear scatter plot button (eg, on scatterplot view) */ + { + event: "clear scatterplot", + from: "init", + to: "done", + action: save, + }, + ]; + +export default createFsmTransitions; diff --git a/client/src/reducers/undoableFsm.ts b/client/src/reducers/undoableFsm.ts deleted file mode 100644 index 7d6b0a35..00000000 --- a/client/src/reducers/undoableFsm.ts +++ /dev/null @@ -1,206 +0,0 @@ -/* -State transition graph for complex action/history interactions. - -Assumed configuration from undoableConfig: - * By convention, "init" is used as the start state for all, and "done" - as the final state. - * Unexpected states will result in an error, plus a clear and cancelPending - side-effect. - -TODO: is is possible there is a more concise format for this, as it is -a fairly repetitive pattern. - -These events are largely one of two types: -a) async operations or multi-event options that should only be committed -upon some success criteria, otherwise cancelled. - -b) compound actions that should be collapsed into a single history change. - -*/ - -import { StateMachine, FsmTransition, FsmActionFn } from "../util/statemachine"; - -const createFsmTransitions = ( - stashPending: FsmActionFn, - cancelPending: FsmActionFn, - applyPending: FsmActionFn, - skip: FsmActionFn, - _clear: FsmActionFn, - save: FsmActionFn -): FsmTransition[] => [ - /* graph selection brushing */ - { - event: "graph brush start", - from: "init", - to: "graph brush in progress", - action: stashPending, - }, - { - event: "graph brush cancel", - from: "graph brush in progress", - to: "done", - action: applyPending, - }, - { - event: "graph brush deselect", - from: "graph brush in progress", - to: "done", - /* if current selection is all, cancelPending. Else, applyPending */ - action: ( - fsm: StateMachine, - transition: FsmTransition, - data: any // eslint-disable-line @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. Requires state typing. - ) => - data.state.graphSelection.selection.mode === "all" - ? cancelPending(fsm, transition, data) - : applyPending(fsm, transition, data), - }, - { - event: "graph brush end", - from: "graph brush in progress", - to: "done", - action: applyPending, - }, - - /* graph selection lasso */ - { - event: "graph lasso start", - from: "init", - to: "graph lasso in progress", - action: stashPending, - }, - { - event: "graph lasso cancel", - from: "graph lasso in progress", - to: "done", - action: applyPending, - }, - { - event: "graph lasso deselect", - from: "graph lasso in progress", - to: "done", - /* if current selection is all, cancelPending. Else, applyPending */ - action: ( - fsm: StateMachine, - transition: FsmTransition, - data: any // eslint-disable-line @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. Requires state typing. - ) => - data.state.graphSelection.selection.mode === "all" - ? cancelPending(fsm, transition, data) - : applyPending(fsm, transition, data), - }, - { - event: "graph lasso end", - from: "graph lasso in progress", - to: "done", - action: applyPending, - }, - - /* Continuous metadata histogram brush selection */ - { - event: "continuous metadata histogram start", - from: "init", - to: "continuous histo select in progress", - action: stashPending, - }, - { - event: "continuous metadata histogram cancel", - from: "continuous histo select in progress", - to: "done", - action: cancelPending, - }, - { - event: "continuous metadata histogram cancel", - from: "init", - to: "done", - action: save, - }, - { - event: "continuous metadata histogram end", - from: "continuous histo select in progress", - to: "done", - action: applyPending, - }, - - /* Single gene request by user */ - { - event: "single user defined gene start", - from: "init", - to: "single user gene request in progress", - action: stashPending, - }, - { - event: "request user defined gene error", - from: "single user gene request in progress", - to: "single user gene error in progress", - action: skip, - }, - { - event: "single user defined gene error", - from: "single user gene error in progress", - to: "done", - action: cancelPending, - }, - { - event: "single user defined gene complete", - from: "single user gene request in progress", - to: "done", - action: applyPending, - }, - - /* Bulk gene request by user */ - { - event: "bulk user defined gene start", - from: "init", - to: "bulk user gene request in progress", - action: stashPending, - }, - { - event: "request user defined gene error", - from: "bulk user gene request in progress", - to: "bulk user gene request error in progress", - action: skip, - }, - { - event: "bulk user defined gene error", - from: "bulk user gene request error in progress", - to: "done", - action: cancelPending, - }, - { - event: "bulk user defined gene complete", - from: "bulk user gene request in progress", - to: "done", - action: applyPending, - }, - - /* Compute Differential Expression button user action */ - { - event: "request differential expression started", - from: "init", - to: "diffexp in progress", - action: stashPending, - }, - { - event: "request user defined gene error", - from: "diffexp in progress", - to: "done", - action: cancelPending, - }, - { - event: "request differential expression success", - from: "diffexp in progress", - to: "done", - action: applyPending, - }, - - /* clear scatter plot button (eg, on scatterplot view) */ - { - event: "clear scatterplot", - from: "init", - to: "done", - action: save, - }, -]; - -export default createFsmTransitions; diff --git a/client/src/reducers/userInfo.js b/client/src/reducers/userInfo.js new file mode 100644 index 00000000..6939e949 --- /dev/null +++ b/client/src/reducers/userInfo.js @@ -0,0 +1,26 @@ +const UserInfo = (state = {}, action) => { + switch (action.type) { + case "initial data load start": + return { + ...state, + loading: true, + error: null, + }; + case "userInfo load complete": + return { + ...state, + loading: false, + error: null, + ...action.userInfo, + }; + case "initial data load error": + return { + ...state, + error: action.error, + }; + default: + return state; + } +}; + +export default UserInfo; diff --git a/client/src/reducers/userInfo.ts b/client/src/reducers/userInfo.ts deleted file mode 100644 index 1eb3088e..00000000 --- a/client/src/reducers/userInfo.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Action } from "redux"; - -export interface UserInfoAction extends Action, User { - userInfo: UserInfoPayload; - error: string; -} - -export interface UserInfoPayload { - is_authenticated: boolean; - username: string; - user_id: string; - email: string; - picture: string; -} - -export interface UserInfoState extends UserInfoPayload { - loading: boolean; - error: string | null; -} - -const UserInfo = ( - state: UserInfoState, - action: UserInfoAction -): UserInfoState => { - switch (action.type) { - case "initial data load start": - return { - ...state, - loading: true, - error: null, - }; - case "userInfo load complete": - return { - ...state, - loading: false, - error: null, - ...action.userInfo, - }; - case "initial data load error": - return { - ...state, - error: action.error, - }; - default: - return state; - } -}; - -export default UserInfo; diff --git a/client/src/util/actionHelpers.ts b/client/src/util/actionHelpers.js similarity index 76% rename from client/src/util/actionHelpers.ts rename to client/src/util/actionHelpers.js index 4da579b5..ccae04af 100644 --- a/client/src/util/actionHelpers.ts +++ b/client/src/util/actionHelpers.js @@ -1,14 +1,13 @@ import sortBy from "lodash.sortby"; /* XXX: cough, cough, ... */ import { postNetworkErrorToast } from "../components/framework/toasters"; -import type { AppDispatch, RootState } from "../reducers"; /* dispatch an action error to the user. Currently we use async toasts. */ -let networkErrorToastKey: string | null = null; -export const dispatchNetworkErrorMessageToUser = (message: string): void => { +let networkErrorToastKey = null; +export const dispatchNetworkErrorMessageToUser = (message) => { if (!networkErrorToastKey) { networkErrorToastKey = postNetworkErrorToast(message); } else { @@ -19,12 +18,9 @@ export const dispatchNetworkErrorMessageToUser = (message: string): void => { /* Catch unexpected errors and make sure we don't lose them! */ -export function catchErrorsWrap( - fn: (dispatch: AppDispatch, getState: () => RootState) => Promise, - dispatchToUser = false -) { - return (dispatch: AppDispatch, getState: () => RootState): void => { - fn(dispatch, getState).catch((error: Error) => { +export function catchErrorsWrap(fn, dispatchToUser = false) { + return (dispatch, getState) => { + fn(dispatch, getState).catch((error) => { console.error(error); if (dispatchToUser) { dispatchNetworkErrorMessageToUser(error.message); @@ -38,10 +34,7 @@ export function catchErrorsWrap( * Wrapper to perform async fetch with some modest error handling * and decoding. Arguments are identical to standard fetch. */ -export const doFetch = async ( - url: string, - init?: RequestInit -): Promise => { +export const doFetch = async (url, init = {}) => { try { // add defaults to the fetch init param. init = { @@ -49,11 +42,11 @@ export const doFetch = async ( credentials: "include", ...init, }; - const acceptType = (init.headers as Headers)?.get("Accept"); + const acceptType = init.headers?.get("Accept"); const res = await fetch(url, init); if ( res.ok && - (!acceptType || res.headers?.get("Content-Type")?.includes(acceptType)) + (!acceptType || res.headers.get("Content-Type").includes(acceptType)) ) { return res; } @@ -73,10 +66,7 @@ export const doFetch = async ( /* Wrapper to perform an async fetch and JSON decode response. */ -export const doJsonRequest = async ( - url: string, - init?: RequestInit -): Promise => { +export const doJsonRequest = async (url, init = {}) => { const res = await doFetch(url, { ...init, headers: new Headers({ Accept: "application/json" }), @@ -87,10 +77,7 @@ export const doJsonRequest = async ( /* Wrapper to perform an async fetch for binary data. */ -export const doBinaryRequest = async ( - url: string, - init?: RequestInit -): Promise => { +export const doBinaryRequest = async (url, init = {}) => { const res = await doFetch(url, { ...init, headers: new Headers({ Accept: "application/octet-stream" }), @@ -114,10 +101,10 @@ Parameters: So [1, 2, 3, 4, 10, 11, 14] -> [ [1, 4], [10, 11], 14] */ export const rangeEncodeIndices = ( - indices: Array, + indices, minRangeLength = 3, sorted = false -): Array => { +) => { if (indices.length === 0) { return indices; } diff --git a/client/src/util/camera.ts b/client/src/util/camera.js similarity index 78% rename from client/src/util/camera.ts rename to client/src/util/camera.js index 93353c28..659ea121 100644 --- a/client/src/util/camera.ts +++ b/client/src/util/camera.js @@ -1,5 +1,4 @@ import { vec2, mat3 } from "gl-matrix"; -import clamp from "./clamp"; const EPSILON = 0.000001; @@ -12,49 +11,41 @@ const panBound = 0.8; const scratch0 = new Float32Array(16); const scratch1 = new Float32Array(16); +function clamp(val, rng) { + return Math.max(Math.min(val, rng[1]), rng[0]); +} + class Camera { - canvas: HTMLCanvasElement; - - prevEvent: { - clientX: number; - clientY: number; - type: string; - }; - - viewMatrix: mat3; - - viewMatrixInv: mat3; - - constructor(canvas: HTMLCanvasElement) { + constructor(canvas) { this.prevEvent = { clientX: 0, clientY: 0, - type: "", + type: 0, }; this.canvas = canvas; this.viewMatrix = mat3.create(); this.viewMatrixInv = mat3.create(); } - view(): mat3 { + view() { return this.viewMatrix; } - invView(): mat3 { + invView() { return this.viewMatrixInv; } - distance(): number { + distance() { return this.viewMatrix[0]; } - pan(dx: number, dy: number): void { + pan(dx, dy) { const m = this.viewMatrix; - const dyRange: [number, number] = [ + const dyRange = [ -panBound - (m[7] + 1) / m[4], panBound - (m[7] - 1) / m[4], ]; - const dxRange: [number, number] = [ + const dxRange = [ -panBound - (m[6] + 1) / m[0], panBound - (m[6] - 1) / m[0], ]; @@ -68,12 +59,12 @@ class Camera { mat3.invert(this.viewMatrixInv, m); } - zoomAt(d: number, x = 0, y = 0): void { + zoomAt(d, x = 0, y = 0) { /* Camera zoom at [x,y] */ const m = this.viewMatrix; - const bounds: [number, number] = [-panBound, panBound]; + const bounds = [-panBound, panBound]; x = clamp(x, bounds); y = clamp(y, bounds); @@ -91,18 +82,13 @@ class Camera { Event handling */ - flush(e: MouseEvent) { + flush(e) { this.prevEvent.type = e.type; this.prevEvent.clientX = e.clientX; this.prevEvent.clientY = e.clientY; } - localPosition( - target: HTMLCanvasElement, - canvasX: number, - canvasY: number, - projectionInvTF: mat3 - ): vec2 { + localPosition(target, canvasX, canvasY, projectionInvTF) { /* Convert mouse position to local */ @@ -122,7 +108,7 @@ class Camera { return pos; } - mousePan(e: MouseEvent, projectionTF: mat3): true { + mousePan(e, projectionTF) { const projectionInvTF = mat3.invert(scratch0, projectionTF); const pos = this.localPosition( this.canvas, @@ -142,7 +128,7 @@ class Camera { return true; } - wheelZoom(e: WheelEvent, projectionTF: mat3): true { + wheelZoom(e, projectionTF) { const { height } = this.canvas; const { deltaY, deltaMode, clientX, clientY } = e; const scale = scaleSpeed * (deltaMode === 1 ? 12 : 1) * (deltaY || 0); @@ -158,7 +144,7 @@ class Camera { return true; } - handleEvent(e: MouseEvent, projectionTF: mat3): boolean { + handleEvent(e, projectionTF) { /* process the event, and return true if camera view changed */ @@ -174,7 +160,7 @@ class Camera { } case "wheel": { - viewChanged = this.wheelZoom(e as WheelEvent, projectionTF); + viewChanged = this.wheelZoom(e, projectionTF); this.flush(e); break; } @@ -187,7 +173,7 @@ class Camera { } } -function attachCamera(canvas: HTMLCanvasElement): Camera { +function attachCamera(canvas) { return new Camera(canvas); } diff --git a/client/src/util/catLabelSort.ts b/client/src/util/catLabelSort.js similarity index 78% rename from client/src/util/catLabelSort.ts rename to client/src/util/catLabelSort.js index 1bf29bf2..030749b7 100644 --- a/client/src/util/catLabelSort.ts +++ b/client/src/util/catLabelSort.js @@ -11,23 +11,20 @@ TL;DR: sort order is: import isNumber from "is-number"; import * as globals from "../globals"; -function caseInsensitiveCompare(a: string, b: string): number { +function caseInsensitiveCompare(a, b) { const textA = String(a).toUpperCase(); const textB = String(b).toUpperCase(); return textA < textB ? -1 : textA > textB ? 1 : 0; } -const catLabelSort = ( - isUserAnno: boolean, - values: Array -): Array => { +const catLabelSort = (isUserAnno, values) => { /* this sort could be memoized for perf */ - const strings: string[] = []; - const ints: string[] = []; - const unassignedOrNaN: string[] = []; + const strings = []; + const ints = []; + const unassignedOrNaN = []; - values.forEach((v: string) => { + values.forEach((v) => { if (isUserAnno && v === globals.unassignedCategoryLabel) { unassignedOrNaN.push(v); } else if (String(v).toLowerCase() === "nan") { diff --git a/client/src/util/centroid.ts b/client/src/util/centroid.js similarity index 77% rename from client/src/util/centroid.ts rename to client/src/util/centroid.js index f4201788..cb6956ec 100644 --- a/client/src/util/centroid.ts +++ b/client/src/util/centroid.js @@ -1,6 +1,5 @@ import quantile from "./quantile"; import { memoize } from "./dataframe/util"; -import { Dataframe } from "./dataframe"; import { unassignedCategoryLabel } from "../globals"; import { createCategorySummaryFromDfCol, @@ -24,13 +23,11 @@ label -> { } */ const getCoordinatesByLabel = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any, - categoryName: string, - categoryDf: Dataframe, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: any, - layoutDf: Dataframe + schema, + categoryName, + categoryDf, + layoutChoice, + layoutDf ) => { const coordsByCategoryLabel = new Map(); // If the coloredBy is not a categorical col @@ -72,7 +69,6 @@ const getCoordinatesByLabel = ( let coords = coordsByCategoryLabel.get(label); if (coords === undefined) { // Get the number of cells which are in the label - // @ts-expect-error ts-migrate(2538) FIXME: Blocked by StateManager/ControlsHelpers const numInLabel = categoryValueCounts[labelIndex]; coords = { hasFinite: false, @@ -98,20 +94,18 @@ const getCoordinatesByLabel = ( return coordsByCategoryLabel; }; -/* +/* calcMedianCentroid calculates the median coordinates for labels in a given category label -> [x-Coordinate, y-Coordinate] */ const calcMedianCentroid = ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any, - categoryName: string, - categoryDf: Dataframe, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: any, - layoutDf: Dataframe + schema, + categoryName, + categoryDf, + layoutChoice, + layoutDf ) => { // generate a map describing the coordinates for each label within the given category const dataMap = getCoordinatesByLabel( @@ -146,15 +140,12 @@ const calcMedianCentroid = ( // A simple function to hash the parameters const hashMedianCentroid = ( - // @ts-expect-error ts-migrate(6133) FIXME: 'schema' is declared but its value is never read. - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any, - categoryName: string, - categoryDf: Dataframe, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - layoutChoice: any, - layoutDf: Dataframe -): string => { + schema, + categoryName, + categoryDf, + layoutChoice, + layoutDf +) => { const category = categoryDf.col(categoryName); const layoutDimNames = layoutChoice.currentDimNames; const layoutX = layoutDf.col(layoutDimNames[0]); diff --git a/client/src/util/clamp.ts b/client/src/util/clamp.js similarity index 83% rename from client/src/util/clamp.ts rename to client/src/util/clamp.js index 7a27902e..b1ae5f1d 100644 --- a/client/src/util/clamp.ts +++ b/client/src/util/clamp.js @@ -8,6 +8,6 @@ * @returns a number */ -export default function clamp(val: number, rng: [number, number]): number { +export default function clamp(val, rng) { return Math.max(Math.min(val, rng[1]), rng[0]); } diff --git a/client/src/util/clip.ts b/client/src/util/clip.js similarity index 70% rename from client/src/util/clip.ts rename to client/src/util/clip.js index 6d7dc118..16514bcd 100644 --- a/client/src/util/clip.ts +++ b/client/src/util/clip.js @@ -1,23 +1,16 @@ -import { NumberArray } from "../common/types/arraytypes"; - /* clip - clip all values in a Array or TypedArray, IN PLACE. Values in array are clipped if less than `lower` or greater than `upper`. If `setTo` is undefined, values less than `lower` will be set to `lower`, -and values greater than `upper` will be set to `upper`. +and values greater than `upper` will be set to `upper`. -If `setTo` is not undefined, values outside the [lower, upper] range will be set to +If `setTo` is not undefined, values outside the [lower, upper] range will be set to `setTo`. */ -export default function clip( - arr: NumberArray, - lower: number, - upper: number, - setTo?: number -): NumberArray { +export default function clip(arr, lower, upper, setTo) { const lowerSet = setTo === undefined ? lower : setTo; const upperSet = setTo === undefined ? upper : setTo; for (let i = 0, l = arr.length; i < l; i += 1) { diff --git a/client/src/util/dataframe/cache.ts b/client/src/util/dataframe/cache.js similarity index 74% rename from client/src/util/dataframe/cache.ts rename to client/src/util/dataframe/cache.js index 15fa191f..bfffeef3 100644 --- a/client/src/util/dataframe/cache.ts +++ b/client/src/util/dataframe/cache.js @@ -10,18 +10,17 @@ objects. */ import { memoize } from "./util"; -import Dataframe from "./dataframe"; -function hashDataframe(df: Dataframe): string { +function hashDataframe(df) { if (df.isEmpty()) return ""; return df.__columnsAccessor.map((c) => c.__id).join(","); } -function noop(df: Dataframe): Dataframe { +function noop(df) { return df; } -const dataframeMemo = (capacity = 100): ((df: Dataframe) => Dataframe) => +const dataframeMemo = (capacity = 100) => memoize(noop, hashDataframe, capacity); export default dataframeMemo; diff --git a/client/src/util/dataframe/dataframe.ts b/client/src/util/dataframe/dataframe.js similarity index 68% rename from client/src/util/dataframe/dataframe.ts rename to client/src/util/dataframe/dataframe.js index b8403ffc..98693bd0 100644 --- a/client/src/util/dataframe/dataframe.ts +++ b/client/src/util/dataframe/dataframe.js @@ -1,44 +1,30 @@ -import { callOnceLazy, memoize, __getMemoId } from "./util"; +import { IdentityInt32Index, isLabelIndex } from "./labelIndex"; +// weird cross-dependency that we should clean up someday... import { isTypedArray, - isAnyArray, - AnyArray, - GenericArrayConstructor, -} from "../../common/types/arraytypes"; -import { IdentityInt32Index, LabelIndex, isLabelIndex } from "./labelIndex"; + isArrayOrTypedArray, + callOnceLazy, + memoize, + __getMemoId, +} from "./util"; import { - summarizeContinuous as _summarizeContinuous, + summarizeContinuous, summarizeCategorical as _summarizeCategorical, } from "./summarize"; import { histogramCategorical as _histogramCategorical, - histogramCategoricalBy as _histogramCategoricalBy, hashCategorical, - hashCategoricalBy, - histogramContinuous as _histogramContinuous, - histogramContinuousBy as _histogramContinuousBy, + histogramContinuous, hashContinuous, - hashContinuousBy, } from "./histogram"; -import { - DataframeValue, - DataframeValueArray, - DataframeColumn, - OffsetType, - OffsetArray, - LabelType, - LabelArray, - ContinuousHistogram, - ContinuousHistogramBy, -} from "./types"; /* -Dataframe is an immutable 2D matrix similar to Python Pandas Dataframe, +Dataframe is an immutable 2D matrix similiar to Python Pandas Dataframe, but (currently) without all of the surrounding support functions. Data is stored in column-major layout, and each column is monomorphic. It supports: -* Relatively efficient create, clone and subset operations +* Relatively efficient creation, cloning and subsetting * Very efficient columnar access (eg, sum down a column), and access to the underlying column arrays. * Data access by row/col offset or label. Labels are reasonably well @@ -46,10 +32,10 @@ It supports: It does not currently support: * Views on matrix subset - for currently known access patterns, - it is more efficient to copy on subsetting, optimizing for access + it is more effiicent to copy on subsetting, optimizing for access speed over memory use. * JS iterators - they are too slow. Use explicit iteration over - offset or labels. + offest or labels. Important assumptions embedded in the API: * Columns are implicitly categorical if they are a JS Array and numeric @@ -86,55 +72,24 @@ dominant pattern in cellxgene. Dataframe **/ -interface DataframeConstructor { - new (...args: ConstructorParameters): Dataframe; -} - -export type MapColumnsCallbackFn = ( - data: DataframeValueArray, - idx: number, - df: Dataframe -) => DataframeValueArray; - -/** @internal */ -function raiseIsNotContinuous(): R { - throw TypeError("Column is not a continuous data type."); -} - class Dataframe { - /** @internal */ - __columns: DataframeValueArray[]; - - /** @internal */ - __columnsAccessor: DataframeColumn[] = []; - - __id: string; - - colIndex: LabelIndex; - - dims: [number, number]; - - length: number; - - rowIndex: LabelIndex; - /** Constructors & factories **/ constructor( - dims: [number, number], - columnarData: DataframeValueArray[], - rowIndex?: LabelIndex | null, - colIndex?: LabelIndex | null, - __columnsAccessor: (DataframeColumn | null)[] = [] // private interface + dims, + columnarData, + rowIndex = null, + colIndex = null, + __columnsAccessor = [] // private interface ) { /* The base constructor is relatively hard to use - as an alternative, see factory methods and clone/slice, below. Parameters: - * dims - 2D array describing intended dimensionality: [nRows,nCols]. + * dims - 2D array describing intendend dimensionality: [nRows,nCols]. * columnarData - JS array, nCols in length, containing array or TypedArray of length nRows. * rowIndex/colIndex - null (create default index using offsets as key), @@ -167,20 +122,14 @@ class Dataframe { Object.freeze(this); } - /** @internal */ - static __errorChecks( - dims: [number, number], - columnarData: AnyArray[], - rowIndex: LabelIndex, - colIndex: LabelIndex - ): void | never { + static __errorChecks(dims, columnarData, rowIndex, colIndex) { const [nRows, nCols] = dims; /* check for expected types */ if (!Array.isArray(columnarData)) { throw new TypeError("Dataframe constructor requires array of columns"); } - if (!columnarData.every((c) => isAnyArray(c))) { + if (!columnarData.every((c) => isArrayOrTypedArray(c))) { throw new TypeError("Dataframe columns must all be Array or TypedArray"); } if (!isLabelIndex(rowIndex)) { @@ -211,12 +160,7 @@ class Dataframe { } } - /** @internal */ - static __compileColumn( - column: DataframeValueArray, - getRowOffset: (label: LabelType) => OffsetType | -1, - getRowLabel: (offset: number) => LabelType | undefined - ): DataframeColumn { + static __compileColumn(column, getRowByOffset, getRowByLabel) { /* Each column accessor is a function which will lookup data by index (ie, is equivalent to dataframe.get(row, col), where 'col' @@ -249,17 +193,14 @@ class Dataframe { */ const { length } = column; const __id = __getMemoId(); - const isContinuous = isTypedArray(column); /* get value by row label */ - const get = function get(rlabel: LabelType): DataframeValue | undefined { - const idx = getRowOffset(rlabel); - if (idx === -1) return undefined; - return column[idx]; + const get = function get(rlabel) { + return column[getRowByOffset(rlabel)]; }; /* get value by row offset */ - const iget = function iget(roffset: OffsetType) { + const iget = function iget(roffset) { return column[roffset]; }; @@ -269,12 +210,12 @@ class Dataframe { }; /* test for row label inclusion in column */ - const has = function has(rlabel: LabelType) { - const offset = getRowOffset(rlabel); + const has = function has(rlabel) { + const offset = getRowByOffset(rlabel); return offset >= 0 && offset < length; }; - const ihas = function ihas(offset: OffsetType) { + const ihas = function ihas(offset) { return offset >= 0 && offset < length; }; @@ -285,88 +226,76 @@ class Dataframe { NOTE: not found return is DIFFERENT than the default Array.indexOf as -1 is a plausible Dataframe row/col label. */ - const _indexOf = function _indexOf(value: DataframeValue) { - let offset: number; - if (isTypedArray(column)) offset = column.indexOf(value as number); - else offset = column.indexOf(value); + const indexOf = function indexOf(value) { + const offset = column.indexOf(value); if (offset === -1) { return undefined; } - return getRowLabel(offset); + return getRowByLabel(offset); }; /* Summarize the column data. Lazy eval, memoized */ - get.summarizeCategorical = callOnceLazy(() => + const summarizeCategorical = callOnceLazy(() => _summarizeCategorical(column) ); - get.summarizeContinuous = isContinuous - ? callOnceLazy(() => _summarizeContinuous(column)) - : raiseIsNotContinuous; + const summarize = callOnceLazy(() => + isTypedArray(column) + ? summarizeContinuous(column) + : summarizeCategorical(column) + ); /* Create histogram bins for this column. Memoized. */ - get.histogramContinuous = isContinuous - ? (bins: number, domain: [number, number]): ContinuousHistogram => - memoize(_histogramContinuous, hashContinuous)(get, bins, domain) - : raiseIsNotContinuous; - get.histogramContinuousBy = isContinuous - ? ( - bins: number, - domain: [number, number], - by: DataframeColumn - ): ContinuousHistogramBy => - memoize(_histogramContinuousBy, hashContinuousBy)( - get, - bins, - domain, - by - ) - : raiseIsNotContinuous; - get.histogramCategorical = () => - memoize(_histogramCategorical, hashCategorical)(get); - get.histogramCategoricalBy = (by: DataframeColumn) => - memoize(_histogramCategoricalBy, hashCategoricalBy)(get, by); + const _memoHistoCat = memoize(_histogramCategorical, hashCategorical); + const histogramCategorical = (by) => _memoHistoCat(get, by); + let histogram = null; + if (isTypedArray(column)) { + const mFn = memoize(histogramContinuous, hashContinuous); + histogram = (bins, domain, by) => mFn(get, bins, domain, by); + } else { + histogram = histogramCategorical; + } + get.summarize = summarize; + get.summarizeCategorical = summarizeCategorical; + get.histogram = histogram; + get.histogramCategorical = histogramCategorical; get.asArray = asArray; get.has = has; get.ihas = ihas; - get.indexOf = _indexOf; + get.indexOf = indexOf; get.iget = iget; get.__id = __id; - get.isContinuous = isContinuous; Object.freeze(get); return get; } - /** @internal */ - __compile(accessors: (DataframeColumn | null)[]): void { + __compile(accessors) { /* Compile data accessors for each column. Use an existing accessor if provided, else compile a new one. */ - const getRowOffset = this.rowIndex.getOffset.bind(this.rowIndex); - const getRowLabel = this.rowIndex.getLabel.bind(this.rowIndex); - this.__columnsAccessor = this.__columns.map( - (column, idx): DataframeColumn => { - if (accessors[idx]) { - return accessors[idx] as DataframeColumn; - } - return Dataframe.__compileColumn(column, getRowOffset, getRowLabel); + const getRowByOffset = this.rowIndex.getOffset.bind(this.rowIndex); + const getRowByLabel = this.rowIndex.getLabel.bind(this.rowIndex); + this.__columnsAccessor = this.__columns.map((column, idx) => { + if (accessors[idx]) { + return accessors[idx]; } - ); + return Dataframe.__compileColumn(column, getRowByOffset, getRowByLabel); + }); Object.freeze(this.__columnsAccessor); } - clone(): Dataframe { + clone() { /* Clone this dataframe */ - return new (this.constructor as DataframeConstructor)( + return new this.constructor( this.dims, [...this.__columns], this.rowIndex, @@ -375,11 +304,7 @@ class Dataframe { ); } - withCol( - label: LabelType, - colData: DataframeValueArray, - withRowIndex?: LabelIndex - ): Dataframe { + withCol(label, colData, withRowIndex = null) { /* Create a new DF, which is `this` plus the new column. Example: const newDf = df.withCol("foo", [1,2,3]); @@ -394,10 +319,11 @@ class Dataframe { the rowIndex from `this` will be used (ie, the rowIndex is unchanged). */ - let dims: [number, number]; - let rowIndex: LabelIndex | null = null; + let dims; + let rowIndex; if (this.isEmpty()) { dims = [colData.length, 1]; + rowIndex = null; } else { dims = [this.dims[0], this.dims[1] + 1]; ({ rowIndex } = this); @@ -411,7 +337,7 @@ class Dataframe { columns.push(colData); const colIndex = this.colIndex.withLabel(label); const columnsAccessor = [...this.__columnsAccessor]; - return new (this.constructor as DataframeConstructor)( + return new this.constructor( dims, columns, rowIndex, @@ -420,10 +346,7 @@ class Dataframe { ); } - withColsFrom( - dataframe: Dataframe, - labels?: Record | LabelType[] - ): Dataframe { + withColsFrom(dataframe, labels) { /* return a new dataframe containing all columns from both `this` and the provided dataframe argument. @@ -449,8 +372,8 @@ class Dataframe { */ // resolve the source and dest label names. - let srcLabels: LabelArray; - let dstLabels: LabelArray; + let srcLabels; + let dstLabels; if (!labels) { // combine all columns dstLabels = dataframe.colIndex.labels(); @@ -485,9 +408,9 @@ class Dataframe { return dataframe; } - // otherwise, build a new dataframe combining columns from both - const srcOffsets = Array.from(dataframe.colIndex.getOffsets(srcLabels)); - if (srcOffsets.some((i) => i === -1)) throw RangeError("Unknown label."); + // otherwise, bulid a new dataframe combining columns from both + + const srcOffsets = srcLabels.map((l) => dataframe.colIndex.getOffset(l)); // check for label collisions if (dstLabels.some(this.hasCol, this)) { @@ -495,12 +418,9 @@ class Dataframe { } // const dims = [this.dims[0], this.dims[1] + dataframe.dims[1]]; - const dims: [number, number] = [ - this.dims[0], - this.dims[1] + srcOffsets.length, - ]; + const dims = [this.dims[0], this.dims[1] + srcOffsets.length]; const { rowIndex } = this; - const columns: DataframeValueArray[] = [ + const columns = [ ...this.__columns, ...srcOffsets.map((i) => dataframe.__columns[i]), ]; @@ -510,7 +430,7 @@ class Dataframe { ...srcOffsets.map((i) => dataframe.__columnsAccessor[i]), ]; - return new (this.constructor as DataframeConstructor)( + return new this.constructor( dims, columns, rowIndex, @@ -519,12 +439,12 @@ class Dataframe { ); } - withColsFromAll(dataframes: Dataframe[] = []): Dataframe { + withColsFromAll(dataframes = []) { dataframes = Array.isArray(dataframes) ? dataframes : [dataframes]; return dataframes.reduce((acc, df) => acc.withColsFrom(df), this); } - dropCol(label: LabelType): Dataframe { + dropCol(label) { /* Create a new dataframe, omitting one columns. @@ -543,15 +463,14 @@ class Dataframe { return Dataframe.empty(); } - const dims: [number, number] = [this.dims[0], this.dims[1] - 1]; + const dims = [this.dims[0], this.dims[1] - 1]; const coffset = this.colIndex.getOffset(label); - if (coffset === -1) throw new RangeError("Unknown label."); const columns = [...this.__columns]; columns.splice(coffset, 1); const colIndex = this.colIndex.dropLabel(label); const columnsAccessor = [...this.__columnsAccessor]; columnsAccessor.splice(coffset, 1); - return new (this.constructor as DataframeConstructor)( + return new this.constructor( dims, columns, this.rowIndex, @@ -560,12 +479,11 @@ class Dataframe { ); } - renameCol(oldLabel: LabelType, newLabel: LabelType): Dataframe { + renameCol(oldLabel, newLabel) { /* Accelerator for dropping a column and then adding it again with a new label */ const coffset = this.colIndex.getOffset(oldLabel); - if (coffset === -1) throw new RangeError("Unknown label."); const colIndex = this.colIndex.dropLabel(oldLabel).withLabel(newLabel); const columns = [...this.__columns]; @@ -576,7 +494,7 @@ class Dataframe { columnsAccessor.push(columnsAccessor[coffset]); columnsAccessor.splice(coffset, 1); - return new (this.constructor as DataframeConstructor)( + return new this.constructor( this.dims, columns, this.rowIndex, @@ -585,21 +503,18 @@ class Dataframe { ); } - replaceColData(label: LabelType, newColData: DataframeValueArray): Dataframe { + replaceColData(label, newColData) { /* Accelerator for dropping a column then adding it again with same label and different values. */ const coffset = this.colIndex.getOffset(label); - if (coffset === -1) throw RangeError("Unknown column label."); const columns = [...this.__columns]; columns[coffset] = newColData; - const columnsAccessor: (DataframeColumn | null)[] = [ - ...this.__columnsAccessor, - ]; + const columnsAccessor = [...this.__columnsAccessor]; columnsAccessor[coffset] = null; - return new (this.constructor as DataframeConstructor)( + return new this.constructor( this.dims, columns, this.rowIndex, @@ -608,8 +523,8 @@ class Dataframe { ); } - static empty(rowIndex?: LabelIndex, colIndex?: LabelIndex): Dataframe { - const dims: [number, number] = [ + static empty(rowIndex = null, colIndex = null) { + const dims = [ rowIndex ? rowIndex.size() : 0, colIndex ? colIndex.size() : 0, ]; @@ -617,10 +532,7 @@ class Dataframe { return new Dataframe(dims, new Array(dims[1]), rowIndex, colIndex); } - static create( - dims: [number, number], - columnarData: DataframeValueArray[] - ): Dataframe { + static create(dims, columnarData) { /* Create a dataframe from raw columnar data. All column arrays must have the same length. Identity indexing will be used. @@ -628,15 +540,11 @@ class Dataframe { Example: const df = Dataframe.create([2,2], [new Uint32Array(2), new Float32Array(2)]); */ - return new Dataframe(dims, columnarData); + return new Dataframe(dims, columnarData, null, null); } - /** @internal */ - __subset( - newRowIndex: LabelIndex | null, - newColIndex: LabelIndex | null - ): Dataframe { - const dims: [number, number] = [...this.dims]; + __subset(newRowIndex, newColIndex) { + const dims = [...this.dims]; /* subset columns */ let { __columns, colIndex, __columnsAccessor } = this; @@ -645,10 +553,8 @@ class Dataframe { __columns = new Array(colOffsets.length); __columnsAccessor = new Array(colOffsets.length); for (let i = 0, l = colOffsets.length; i < l; i += 1) { - const colOffset = colOffsets[i]; - if (colOffset === -1) throw new RangeError("Unexpected column offset."); - __columns[i] = this.__columns[colOffset]; - __columnsAccessor[i] = this.__columnsAccessor[colOffset]; + __columns[i] = this.__columns[colOffsets[i]]; + __columnsAccessor[i] = this.__columnsAccessor[colOffsets[i]]; } colIndex = newColIndex; dims[1] = colOffsets.length; @@ -658,13 +564,9 @@ class Dataframe { if (newRowIndex) { const rowOffsets = this.rowIndex.getOffsets(newRowIndex.labels()); __columns = __columns.map((col) => { - const newCol = new (col.constructor as GenericArrayConstructor< - typeof col - >)(rowOffsets.length); + const newCol = new col.constructor(rowOffsets.length); for (let i = 0, l = rowOffsets.length; i < l; i += 1) { - const rowOffset = rowOffsets[i]; - if (rowOffset === -1) throw new RangeError("Unexpected row offset."); - newCol[i] = col[rowOffset]; + newCol[i] = col[rowOffsets[i]]; } return newCol; }); @@ -683,11 +585,7 @@ class Dataframe { ); } - subset( - rowLabels: LabelArray | null, - colLabels: LabelArray | null, - withRowIndex?: LabelIndex | null - ): Dataframe { + subset(rowLabels, colLabels = null, withRowIndex = null) { /* Subset by row/col labels. @@ -709,11 +607,7 @@ class Dataframe { return this.__subset(rowIndex, colIndex); } - isubset( - rowOffsets: OffsetArray | null, - colOffsets: OffsetArray | null, - withRowIndex?: LabelIndex | null - ): Dataframe { + isubset(rowOffsets, colOffsets = null, withRowIndex = null) { /* Subset by row/col offset. @@ -722,14 +616,14 @@ class Dataframe { indexing. If withRowIndex is a label index object, it will be used for the new dataframe. */ - let rowIndex: LabelIndex | null = null; + let rowIndex = null; if (withRowIndex) { rowIndex = withRowIndex; } else if (rowOffsets) { rowIndex = this.rowIndex.isubset(rowOffsets); } - let colIndex: LabelIndex | null = null; + let colIndex = null; if (colOffsets) { colIndex = this.colIndex.isubset(colOffsets); } @@ -737,11 +631,7 @@ class Dataframe { return this.__subset(rowIndex, colIndex); } - isubsetMask( - rowMask: Uint8Array | boolean[] | null, - colMask: Uint8Array | boolean[] | null, - withRowIndex?: LabelIndex | null - ): Dataframe { + isubsetMask(rowMask, colMask = null, withRowIndex = null) { /* Subset on row/column based upon a truthy/falsey array (a mask). @@ -759,10 +649,7 @@ class Dataframe { } /* convert masks to lists - method wastes space, but is fast */ - const toList = ( - mask: Uint8Array | boolean[] | null | undefined, - maxSize: number - ) => { + const toList = (mask, maxSize) => { if (!mask) { return null; } @@ -785,12 +672,12 @@ class Dataframe { Data access with row/col. **/ - columns(): DataframeColumn[] { + columns() { /* return all column accessors as an array, in offset order */ return [...this.__columnsAccessor]; } - col(columnLabel: LabelType): DataframeColumn { + col(columnLabel) { /* Return accessor bound to a column. Allows random row access based upon the row indexing. Returns undefined if the @@ -807,44 +694,36 @@ class Dataframe { See __compile() for the functions available in a column accessor. */ const coff = this.colIndex.getOffset(columnLabel); - if (coff === -1) throw RangeError("Unknown label."); return this.__columnsAccessor[coff]; } - icol(columnOffset: OffsetType): DataframeColumn { + icol(columnOffset) { /* Return column accessor by offset. */ - if ( - Number.isInteger(columnOffset) && - columnOffset >= 0 && - columnOffset < this.__columnsAccessor.length - ) { - return this.__columnsAccessor[columnOffset]; - } - throw new RangeError("Unknown offset."); + return Number.isInteger(columnOffset) + ? this.__columnsAccessor[columnOffset] + : undefined; } - at(r: LabelType, c: LabelType): DataframeValue { + at(r, c) { /* Access a single value, for a row/col label pair. - For performance reasons, there are no bounds or existence + For performance reasons, there are no bounds or existance checks on labels, and no defined behavior when these are supplied. May return undefined, throw an Error, or do something else for - non-existent labels. If you want predictable out-of-bounds + non-existant labels. If you want predictable out-of-bounds behavior, use has(), eg, const myVal = df.has(r,l) ? df.at(r,l) : undefined; */ const coff = this.colIndex.getOffset(c); const roff = this.rowIndex.getOffset(r); - if (coff === undefined || roff === undefined) - throw new RangeError("Unknown row or column label."); return this.__columns[coff][roff]; } - iat(r: OffsetType, c: OffsetType): DataframeValue { + iat(r, c) { /* Access a single value, for a row/col offset (integer) position. @@ -854,12 +733,10 @@ class Dataframe { const myVal = df.ihas(r, c) ? df.iat(r, c) : undefined; */ - if (c >= 0 && c < this.dims[1] && r >= 0 && r < this.dims[0]) - return this.__columns[c][r]; - throw new RangeError("Unknown row or column index."); + return this.__columns[c][r]; } - has(r: LabelType, c: LabelType): boolean { + has(r, c) { /* Test if row/col labels exist in the dataframe - returns true/false */ @@ -869,7 +746,7 @@ class Dataframe { return coff >= 0 && coff < nCols && roff >= 0 && roff < nRows; } - ihas(r: number, c: number): boolean { + ihas(r, c) { /* Test if row/col offset (integer) position exists in the dataframe - returns true/false @@ -885,23 +762,14 @@ class Dataframe { ); } - hasCol(c: LabelType): boolean { + hasCol(c) { /* Test if col label exists - return true/false */ - const coff = this.colIndex.getOffset(c); - return coff !== -1; + return !!this.col(c); } - ihasCol(i: number): boolean { - /* - Test if col offset exists - return true/false - */ - const [, nCols] = this.dims; - return i >= 0 && i < nCols; - } - - isEmpty(): boolean { + isEmpty() { /* Return true if this is an empty dataframe, ie, has dimensions [0,0] */ @@ -916,7 +784,7 @@ class Dataframe { add these as useful. ****/ - mapColumns(callback: MapColumnsCallbackFn): Dataframe { + mapColumns(callback) { /* map all columns in the dataframe, returning a new dataframe comprised of the return values, with the same index as the original dataframe. @@ -926,10 +794,10 @@ class Dataframe { const columns = this.__columns.map((colData, colIdx) => callback(colData, colIdx, this) ); - const columnsAccessor: (DataframeColumn | null)[] = columns.map((c, idx) => - this.__columns[idx] === c ? this.__columnsAccessor[idx] : null + const columnsAccessor = columns.map((c, idx) => + this.__columns[idx] === c ? this.__columnsAccessor[idx] : undefined ); - return new (this.constructor as DataframeConstructor)( + return new this.constructor( this.dims, columns, this.rowIndex, @@ -937,6 +805,29 @@ class Dataframe { columnsAccessor ); } + + /* + Map & reduce of column or row + + TODO remainder of map/reduce functions: mapCol, mapRow, reduceRow, ... + */ + /* comment out until we have a use for this + + reduceCol(clabel, callback, initialValue) { + const coff = this.colIndex.getOffset(clabel); + const column = this.__columns[coff]; + let start = 0; + let acc = initialValue; + if (initialValue === undefined) { + acc = column[0]; + start = 1; + } + for (let i = start, l = column.length; i < l; i += 1) { + acc = callback(acc, column[i]); + } + return acc; + } + */ } export default Dataframe; diff --git a/client/src/util/dataframe/histogram.ts b/client/src/util/dataframe/histogram.js similarity index 61% rename from client/src/util/dataframe/histogram.ts rename to client/src/util/dataframe/histogram.js index 6e1fecd2..48d6a19e 100644 --- a/client/src/util/dataframe/histogram.ts +++ b/client/src/util/dataframe/histogram.js @@ -1,27 +1,15 @@ /* Dataframe histogram */ -import { NumberArray } from "../../common/types/arraytypes"; -import { - DataframeColumn, - ContinuousHistogram, - ContinuousHistogramBy, - CategoricalHistogram, - CategoricalHistogramBy, -} from "./types"; +import { isTypedArray } from "./util"; -export function histogramContinuous( - column: DataframeColumn, - bins: number, - domain: [number, number] -): ContinuousHistogram { +function _histogramContinuous(column, bins, min, max) { const valBins = new Array(bins).fill(0); if (!column) { return valBins; } - const [min, max] = domain; const binWidth = (max - min) / bins; - const colArray: NumberArray = column.asArray() as NumberArray; + const colArray = column.asArray(); for (let r = 0, len = colArray.length; r < len; r += 1) { const val = colArray[r]; if (val <= max && val >= min) { @@ -33,20 +21,14 @@ export function histogramContinuous( return valBins; } -export function histogramContinuousBy( - column: DataframeColumn, - bins: number, - domain: [number, number], - by: DataframeColumn -): ContinuousHistogramBy { +function _histogramContinuousBy(column, bins, min, max, by) { const byMap = new Map(); if (!column || !by) { return byMap; } - const [min, max] = domain; const binWidth = (max - min) / bins; const byArray = by.asArray(); - const colArray = column.asArray() as NumberArray; + const colArray = column.asArray(); for (let r = 0, len = colArray.length; r < len; r += 1) { const byBin = byArray[r]; let valBins = byMap.get(byBin); @@ -64,9 +46,7 @@ export function histogramContinuousBy( return byMap; } -export function histogramCategorical( - column: DataframeColumn -): CategoricalHistogram { +function _histogramCategorical(column) { const valMap = new Map(); if (!column) { return valMap; @@ -83,10 +63,7 @@ export function histogramCategorical( return valMap; } -export function histogramCategoricalBy( - column: DataframeColumn, - by: DataframeColumn -): CategoricalHistogramBy { +function _histogramCategoricalBy(column, by) { const byMap = new Map(); if (!column || !by) { return byMap; @@ -110,38 +87,49 @@ export function histogramCategoricalBy( return byMap; } +/* +Count category occupancy. Optional group-by category. +*/ +export function histogramCategorical(column, by) { + if (by && isTypedArray(by)) { + throw new Error("Group by column must be categorical"); + } + return by + ? _histogramCategoricalBy(column, by) + : _histogramCategorical(column); +} + /* Memoization hash for histogramCategorical() */ -export function hashCategorical(column: DataframeColumn): string { +export function hashCategorical(column, by) { + if (by) { + return `${column.__id}:${by.__id}`; + } return `${column.__id}:`; } -export function hashCategoricalBy( - column: DataframeColumn, - by: DataframeColumn -): string { - return `${column.__id}:${by.__id}`; +/* +Bin counts for continuous/scalar values, with optional group-by category. +Values outside domain are ignored. +*/ +export function histogramContinuous(column, bins = 40, domain = [0, 1], by) { + if (by && isTypedArray(by)) { + throw new Error("Group by column must be categorical"); + } + const [min, max] = domain; + return by + ? _histogramContinuousBy(column, bins, min, max, by) + : _histogramContinuous(column, bins, min, max); } /* Memoization hash for histogramContinuous */ -export function hashContinuous( - column: DataframeColumn, - bins: number, - domain: [number, number] -): string { +export function hashContinuous(column, bins = "", domain = [0, 0], by) { const [min, max] = domain; + if (by) { + return `${column.__id}:${bins}:${min}:${max}:${by.__id}`; + } return `${column.__id}::${bins}:${min}:${max}`; } - -export function hashContinuousBy( - column: DataframeColumn, - bins: number, - domain: [number, number], - by: DataframeColumn -): string { - const [min, max] = domain; - return `${column.__id}:${bins}:${min}:${max}:${by.__id}`; -} diff --git a/client/src/util/dataframe/index.js b/client/src/util/dataframe/index.js new file mode 100644 index 00000000..0432a6e5 --- /dev/null +++ b/client/src/util/dataframe/index.js @@ -0,0 +1,8 @@ +export { default as Dataframe } from "./dataframe"; +export { + DenseInt32Index, + IdentityInt32Index, + KeyIndex, + isLabelIndex, +} from "./labelIndex"; +export { default as dataframeMemo } from "./cache"; diff --git a/client/src/util/dataframe/index.ts b/client/src/util/dataframe/index.ts deleted file mode 100644 index 703d81be..00000000 --- a/client/src/util/dataframe/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -export { default as Dataframe } from "./dataframe"; -export { - DenseInt32Index, - IdentityInt32Index, - KeyIndex, - isLabelIndex, -} from "./labelIndex"; -export { default as dataframeMemo } from "./cache"; -export type { - LabelType, - DataframeValue, - DataframeValueArray, - DataframeColumn, - ContinuousHistogram, - ContinuousHistogramBy, - CategoricalHistogram, - CategoricalHistogramBy, - ContinuousColumnSummary, - CategoricalColumnSummary, -} from "./types"; -export type { LabelIndex } from "./labelIndex"; diff --git a/client/src/util/dataframe/labelIndex.js b/client/src/util/dataframe/labelIndex.js new file mode 100644 index 00000000..fe8a48fe --- /dev/null +++ b/client/src/util/dataframe/labelIndex.js @@ -0,0 +1,396 @@ +/* eslint-disable max-classes-per-file -- Classes are interrelated*/ +/** +Label indexing - map a label to & from an integer offset. See Dataframe +for how this is used. +**/ + +import { rangeFill as fillRange } from "../range"; +import { __getMemoId } from "./util"; + +/* +Private utility functions +*/ +function extent(tarr) { + let min = 0x7fffffff; + let max = ~min; // eslint-disable-line no-bitwise -- Establishes 0 of same size + for (let i = 0, l = tarr.length; i < l; i += 1) { + const v = tarr[i]; + if (v < min) { + min = v; + } + if (v > max) { + max = v; + } + } + return [min, max]; +} + +class IdentityInt32Index { + /* + identity/noop index, with small assumptions that labels are int32 + */ + constructor(maxOffset) { + this.maxOffset = maxOffset; + } + + get __id() { + return `IdentityInt32Index_${this.maxOffset}`; + } + + labels() { + // memoize + const k = fillRange(new Int32Array(this.maxOffset)); + this.labels = function labels() { + return k; + }; + return k; + } + + getOffset(i) { + // label to offset + return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined; + } + + getOffsets(arr) { + // labels to offsets + return arr.map((i) => this.getOffset(i)); + } + + getLabel(i) { + // offset to label + return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined; + } + + getLabels(arr) { + // offsets to labels + return arr.map((i) => this.getLabel(i)); + } + + size() { + return this.maxOffset; + } + + __promote(labelArray) { + /* + time/space decision - based on the resulting density + */ + const [minLabel, maxLabel] = extent(labelArray); + if (minLabel === 0 && maxLabel === labelArray.length - 1) + return new IdentityInt32Index(labelArray.length); + + const labelSpaceSize = maxLabel - minLabel + 1; + const density = labelSpaceSize / this.maxOffset; + /* 0.1 is a magic number, that needs testing to optimize */ + if (density < 0.1) { + return new KeyIndex(labelArray); + } + return new DenseInt32Index(labelArray, [minLabel, maxLabel]); + } + + subset(labels) { + /* validate subset */ + const { maxOffset } = this; + for (let i = 0, l = labels.length; i < l; i += 1) { + const label = labels[i]; + if (!Number.isInteger(label) || label < 0 || label >= maxOffset) + throw new RangeError(`offset or label: ${label}`); + } + return this.__promote(labels); + } + + /* identity index - labels are offsets */ + isubset(offsets) { + return this.subset(offsets); + } + + /* identity index - labels are offsets */ + isubsetMask(mask) { + let count = 0; + if (mask.length !== this.maxOffset) { + throw new RangeError("mask has invalid length for index"); + } + let labels = new Int32Array(mask.length); + for (let i = 0, l = mask.length; i < l; i += 1) { + if (mask[i]) { + labels[count] = i; + count += 1; + } + } + labels = labels.slice(0, count); + return this.subset(labels); + } + + withLabel(label) { + if (label === this.maxOffset) { + return new IdentityInt32Index(label + 1); + } + return this.__promote([...this.labels(), label]); + } + + withLabels(labels) { + return this.__promote([...this.labels(), ...labels]); + } + + dropLabel(label) { + if (label === this.maxOffset - 1) { + return new IdentityInt32Index(label); + } + const labelArray = [...this.labels()]; + labelArray.splice(labelArray.indexOf(label), 1); + return this.__promote(labelArray); + } +} + +class DenseInt32Index { + /* + DenseInt32Index indexes integer labels, and uses Int32Array typed arrays + for both forward and reverse indexing. This means that the min/max range + of the forward index labels must be known a priori (so that the index + array can be pre-allocated). + */ + constructor(labels, labelRange = null) { + if (labels.constructor !== Int32Array) { + labels = new Int32Array(labels); + } + + if (!labelRange) { + labelRange = extent(labels); + } + const [minLabel, maxLabel] = labelRange; + const labelSpaceSize = maxLabel - minLabel + 1; + const index = new Int32Array(labelSpaceSize).fill(-1); + for (let i = 0, l = labels.length; i < l; i += 1) { + const label = labels[i]; + index[label - minLabel] = i; + } + + this.minLabel = minLabel; + this.rindex = labels; + this.index = index; + this.__id = __getMemoId(); + this.__compile(); + } + + __compile() { + const { minLabel, index, rindex } = this; + this.getOffset = function getOffset(l) { + if (!Number.isInteger(l)) return undefined; + const offset = index[l - minLabel]; + return offset === -1 ? undefined : offset; + }; + + this.getOffsets = function getOffsets(arr) { + return arr.map((i) => this.getOffset(i)); + }; + + this.getLabel = function getLabel(i) { + return Number.isInteger(i) ? rindex[i] : undefined; + }; + + this.getLabels = function getLabels(arr) { + return arr.map((i) => this.getLabel(i)); + }; + } + + labels() { + return this.rindex; + } + + size() { + return this.rindex.length; + } + + __promote(labelArray) { + /* + time/space decision - if we are going to use less than 10% of the + dense index space, switch to a KeyIndex (which is slower, but uses + less memory for sparse label spaces). + */ + const [minLabel, maxLabel] = extent(labelArray); + const labelSpaceSize = maxLabel - minLabel + 1; + const density = labelSpaceSize / this.rindex.length; + /* 0.1 is a magic number, that needs testing to optimize */ + if (density < 0.1) { + return new KeyIndex(labelArray); + } + return new DenseInt32Index(labelArray, [minLabel, maxLabel]); + } + + subset(labels) { + /* validate subset */ + for (let i = 0, l = labels.length; i < l; i += 1) { + const label = labels[i]; + const offset = this.getOffset(label); + if (offset === undefined || offset === -1) + throw new RangeError(`unknown label: ${label}`); + } + return this.__promote(labels); + } + + isubset(offsets) { + /* validate subset */ + const { rindex } = this; + const maxOffset = rindex.length; + const labels = new Int32Array(offsets.length); + for (let i = 0, l = offsets.length; i < l; i += 1) { + const offset = offsets[i]; + if (offset < 0 || offset >= maxOffset) + throw new RangeError(`out of bounds offset: ${offset}`); + labels[i] = rindex[offset]; + } + return this.__promote(labels); + } + + isubsetMask(mask) { + const { rindex } = this; + if (mask.length !== rindex.length) + throw new RangeError("mask has invalid length for index"); + let count = 0; + let labels = new Int32Array(mask.length); + for (let i = 0, l = mask.length; i < l; i += 1) { + if (mask[i]) { + labels[count] = rindex[i]; + count += 1; + } + } + labels = labels.slice(0, count); + return this.__promote(labels); + } + + withLabel(label) { + return this.__promote([...this.labels(), label]); + } + + withLabels(labels) { + return this.__promote([...this.labels(), ...labels]); + } + + dropLabel(label) { + const labelArray = [...this.labels()]; + labelArray.splice(labelArray.indexOf(label), 1); + return this.__promote(labelArray); + } +} + +class KeyIndex { + /* + KeyIndex indexes arbitrary JS primitive types, and uses a Map() + as its core data structure. + */ + constructor(labels) { + const index = new Map(); + if (labels === undefined) { + labels = []; + } + const rindex = labels; + labels.forEach((v, i) => { + index.set(v, i); + }); + + if (index.size !== rindex.length) { + /* if true, there was a duplicate in the keys */ + throw new Error("duplicate label provided to KeyIndex"); + } + + this.index = index; + this.rindex = rindex; + this.__id = __getMemoId(); + this.__compile(); + } + + __compile() { + const { index, rindex } = this; + this.getOffset = function getOffset(k) { + return index.get(k); + }; + + this.getOffsets = function getOffsets(arr) { + return arr.map((l) => this.getOffset(l)); + }; + + this.getLabel = function getLabel(i) { + return Number.isInteger(i) ? rindex[i] : undefined; + }; + + this.getLabels = function getLabels(arr) { + return arr.map((i) => this.getLabel(i)); + }; + } + + labels() { + return this.rindex; + } + + size() { + return this.rindex.length; + } + + subset(labels) { + /* validate subset */ + for (let i = 0, l = labels.length; i < l; i += 1) { + const label = labels[i]; + const offset = this.getOffset(label); + if (offset === undefined || offset === -1) { + throw new RangeError(`unknown label: ${label}`); + } + } + + return new KeyIndex(labels); + } + + isubset(offsets) { + const { rindex } = this; + const maxOffset = rindex.length; + const labels = new Array(offsets.length); + for (let i = 0, l = offsets.length; i < l; i += 1) { + const offset = offsets[i]; + if (offset < 0 || offset >= maxOffset) + throw new RangeError(`out of bounds offset: ${offset}`); + labels[i] = rindex[offset]; + } + + return new KeyIndex(labels); + } + + isubsetMask(mask) { + const { rindex } = this; + if (mask.length !== rindex.length) + throw new RangeError("mask has invalid length for index"); + let labels = new Array(mask.length); + let count = 0; + for (let i = 0, l = mask.length; i < l; i += 1) { + if (mask[i]) { + labels[count] = rindex[i]; + count += 1; + } + } + labels = labels.slice(0, count); + return new KeyIndex(labels); + } + + withLabel(label) { + return new KeyIndex([...this.rindex, label]); + } + + withLabels(labels) { + return new KeyIndex([...this.rindex, ...labels]); + } + + dropLabel(label) { + const idx = this.rindex.indexOf(label); + const labelArray = [...this.rindex]; + labelArray.splice(idx, 1); + return new KeyIndex(labelArray); + } +} + +function isLabelIndex(i) { + return ( + i instanceof IdentityInt32Index || + i instanceof DenseInt32Index || + i instanceof KeyIndex + ); +} + +export { DenseInt32Index, IdentityInt32Index, KeyIndex, isLabelIndex }; +/* eslint-enable max-classes-per-file -- enable*/ diff --git a/client/src/util/dataframe/labelIndex.ts b/client/src/util/dataframe/labelIndex.ts deleted file mode 100644 index 668735b3..00000000 --- a/client/src/util/dataframe/labelIndex.ts +++ /dev/null @@ -1,495 +0,0 @@ -/* eslint-disable max-classes-per-file -- Classes are interrelated*/ - -/** -Label indexing - map a label to & from an integer offset. See Dataframe -for how this is used. -**/ - -import { rangeFill as fillRange } from "../range"; -import { __getMemoId } from "./util"; -import { OffsetArray, LabelType, LabelArray, GenericLabelArray } from "./types"; - -export abstract class LabelIndexBase { - readonly __id: string; // memoization helper - - constructor(id: string) { - this.__id = id; - } - - abstract labels(): LabelArray; - - /** - * Look up the offset for the label. - * - * @param label - label to look up - * @returns - offset number or -1 if not found. - */ - abstract getOffset(label: LabelType): number; - - getOffsets(labels: LabelArray): Int32Array { - // labels to offsets - const result = new Int32Array(labels.length); - for (let i = 0; i < labels.length; i += 1) { - result[i] = this.getOffset(labels[i]); - } - return result; - } - - /** - * Look up the label for the offset. - * - * @param offset - offset to look up - * @returns - label or undefined if not found. - */ - abstract getLabel(offset: number): LabelType | undefined; - - getLabels(offsets: OffsetArray): (LabelType | undefined)[] { - // offsets to labels - const result = new Array(offsets.length); - for (let i = 0; i < offsets.length; i += 1) { - result[i] = this.getLabel(offsets[i]); - } - return result; - } - - abstract size(): number; - - abstract subset(labels: LabelArray): LabelIndexBase; - - abstract isubset(offsets: OffsetArray): LabelIndexBase; - - abstract isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase; - - abstract withLabel(label: LabelType): LabelIndexBase; - - abstract withLabels(labels: LabelArray): LabelIndexBase; - - abstract dropLabel(label: LabelType): LabelIndexBase; -} - -export class IdentityInt32Index extends LabelIndexBase { - readonly maxOffset: number; - - /* - identity/noop index, with small assumptions that labels are int32 - */ - constructor(maxOffset: number) { - super(`IdentityInt32Index_${maxOffset}`); - this.maxOffset = maxOffset; - } - - labels(): LabelArray { - // memoize - const k = fillRange(new Int32Array(this.maxOffset)); - this.labels = function labels() { - return k; - }; - return k; - } - - getOffset(label: LabelType): number { - // label to offset - return Number.isInteger(label) && label >= 0 && label < this.maxOffset - ? (label as number) - : -1; - } - - getLabel(offset: number): number | undefined { - // offset to label - return Number.isInteger(offset) && offset >= 0 && offset < this.maxOffset - ? offset - : undefined; - } - - size(): number { - return this.maxOffset; - } - - /** @internal */ - __promote(labelArray: LabelArray, allInts: boolean): LabelIndexBase { - /* - time/space decision - based on the resulting density - */ - if (labelArray.length === 0) return new KeyIndex(Array.from(labelArray)); - if (allInts) { - const [minLabel, maxLabel] = extent( - labelArray as GenericLabelArray // safe, as allInts is true - ); - if (minLabel === 0 && maxLabel === labelArray.length - 1) - return new IdentityInt32Index(labelArray.length); - - const labelSpaceSize = maxLabel - minLabel + 1; - const density = labelSpaceSize / this.maxOffset; - /* 0.1 is a magic number which needs testing to optimize */ - if (density < 0.1) { - return new KeyIndex(Array.from(labelArray)); - } - return new DenseInt32Index(labelArray as GenericLabelArray, [ - minLabel, - maxLabel, - ]); - } - return new KeyIndex(Array.from(labelArray)); - } - - subset(labels: LabelArray): LabelIndexBase { - /* validate subset */ - const { maxOffset } = this; - for (let i = 0, l = labels.length; i < l; i += 1) { - const label = labels[i]; - if (!Number.isInteger(label) || label < 0 || label >= maxOffset) - throw new RangeError(`label: ${label}`); - } - return this.__promote(labels, true); - } - - /* identity index - labels are offsets */ - isubset(offsets: OffsetArray): LabelIndexBase { - /* validate isubset */ - const { maxOffset } = this; - for (let i = 0, l = offsets.length; i < l; i += 1) { - const offset = offsets[i]; - if (!Number.isInteger(offset) || offset < 0 || offset >= maxOffset) - throw new RangeError(`offset: ${offset}`); - } - if (!(offsets instanceof Int32Array)) { - offsets = new Int32Array(offsets); - } - return this.__promote(offsets, true); - } - - /* identity index - labels are offsets */ - isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase { - let count = 0; - if (mask.length !== this.maxOffset) { - throw new RangeError("mask has invalid length for index"); - } - let labels = new Int32Array(mask.length); - for (let i = 0, l = mask.length; i < l; i += 1) { - if (mask[i]) { - labels[count] = i; - count += 1; - } - } - labels = labels.slice(0, count); - return this.subset(labels); - } - - withLabel(label: LabelType): LabelIndexBase { - if (label === this.maxOffset) { - return new IdentityInt32Index(label + 1); - } - return this.__promote([...this.labels(), label], Number.isInteger(label)); - } - - withLabels(labels: LabelArray): LabelIndexBase { - return this.__promote( - [...this.labels(), ...labels], - labels.every(Number.isInteger) - ); - } - - dropLabel(label: LabelType): LabelIndexBase { - if (!Number.isInteger(label) || label < 0 || label > this.maxOffset - 1) - throw new RangeError("Invalid label."); - if (label === this.maxOffset - 1) { - return new IdentityInt32Index(label); - } - const labelArray = [...this.labels()]; - labelArray.splice(labelArray.indexOf(label as number), 1); - return this.__promote(labelArray, true); - } -} - -export class DenseInt32Index extends LabelIndexBase { - getLabel: (offset: number) => number | undefined; - - getOffset: (label: LabelType) => number; - - index: Int32Array; - - minLabel: number; - - rindex: Int32Array; - - /* - DenseInt32Index indexes integer labels, and uses Int32Array typed arrays - for both forward and reverse indexing. This means that the min/max range - of the forward index labels must be known a priori (so that the index - array can be pre-allocated). - */ - constructor( - labels: GenericLabelArray, - labelRange?: [number, number] - ) { - super(__getMemoId()); - const int32Labels = - labels instanceof Int32Array ? labels : new Int32Array(labels); - if (!labelRange) { - labelRange = extent(int32Labels); - } - const [minLabel, maxLabel] = labelRange; - const labelSpaceSize = maxLabel - minLabel + 1; - const index = new Int32Array(labelSpaceSize).fill(-1); - for (let i = 0, l = labels.length; i < l; i += 1) { - const label = labels[i]; - index[label - minLabel] = i; - } - - this.minLabel = minLabel; - this.rindex = int32Labels; - this.index = index; - - this.getOffset = function getOffset(label: LabelType) { - if (!Number.isInteger(label)) return -1; - const lblIdx: number = label - minLabel; - if (lblIdx < 0 || lblIdx >= index.length) return -1; - const offset = index[lblIdx]; - return offset; - }; - - this.getLabel = function getLabel(offset: number) { - return Number.isInteger(offset) ? labels[offset] : undefined; - }; - } - - labels(): LabelArray { - return this.rindex; - } - - size(): number { - return this.rindex.length; - } - - /** @internal */ - __promote(labelArray: LabelArray, allInts: boolean): LabelIndexBase { - /* - time/space decision - if we are going to use less than 10% of the - dense index space, switch to a KeyIndex (which is slower, but uses - less memory for sparse label spaces). - */ - if (labelArray.length === 0) return new KeyIndex(Array.from(labelArray)); - if (allInts) { - if (!(labelArray instanceof Int32Array)) { - labelArray = new Int32Array(labelArray as number[]); - } - const [minLabel, maxLabel] = extent( - labelArray as GenericLabelArray // safe, as allInts is true - ); - const labelSpaceSize = maxLabel - minLabel + 1; - const density = labelSpaceSize / this.rindex.length; - /* 0.1 is a magic number, that needs testing to optimize */ - if (density < 0.1) { - return new KeyIndex(Array.from(labelArray)); - } - return new DenseInt32Index(labelArray as GenericLabelArray, [ - minLabel, - maxLabel, - ]); - } - return new KeyIndex(Array.from(labelArray)); - } - - subset(labels: LabelArray): LabelIndexBase { - /* validate subset */ - for (let i = 0, l = labels.length; i < l; i += 1) { - const label = labels[i]; // if not a number, getOffset will error - const offset = this.getOffset(label as number); - if (offset === -1) throw new RangeError(`unknown label: ${label}`); - } - return this.__promote(labels as GenericLabelArray, true); - } - - isubset(offsets: OffsetArray): LabelIndexBase { - /* validate subset */ - const { rindex } = this; - const maxOffset = rindex.length; - const labels = new Int32Array(offsets.length); - for (let i = 0, l = offsets.length; i < l; i += 1) { - const offset = offsets[i]; - if (offset < 0 || offset >= maxOffset) - throw new RangeError(`out of bounds offset: ${offset}`); - labels[i] = rindex[offset]; - } - return this.__promote(labels, true); - } - - isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase { - const { rindex } = this; - if (mask.length !== rindex.length) - throw new RangeError("mask has invalid length for index"); - let count = 0; - let labels = new Int32Array(mask.length); - for (let i = 0, l = mask.length; i < l; i += 1) { - if (mask[i]) { - labels[count] = rindex[i]; - count += 1; - } - } - labels = labels.slice(0, count); - return this.__promote(labels, true); - } - - withLabel(label: LabelType): LabelIndexBase { - return this.__promote([...this.labels(), label], Number.isInteger(label)); - } - - withLabels(labels: LabelArray): LabelIndexBase { - return this.__promote( - [...this.labels(), ...labels], - labels.every(Number.isInteger) - ); - } - - dropLabel(label: LabelType): LabelIndexBase { - if (!Number.isInteger(label)) throw new RangeError("Invalid label."); - const labelArray = [...this.labels()]; - labelArray.splice(labelArray.indexOf(label as number), 1); - return this.__promote( - new Int32Array(labelArray as GenericLabelArray), - true - ); - } -} - -export class KeyIndex extends LabelIndexBase { - getLabel: (offset: number) => LabelType | undefined; - - getOffset: (label: LabelType) => number | -1; - - index: Map; - - rindex: (string | number)[]; - - /* - KeyIndex indexes arbitrary JS primitive types, and uses a Map() - as its core data structure. - */ - constructor(labels: Array) { - super(__getMemoId()); - const index = new Map(); - if (labels === undefined) { - labels = []; - } - if (!Array.isArray(labels)) { - labels = Array.from(labels); - } - const rindex = labels; - labels.forEach((v, i) => { - index.set(v, i); - }); - - if (index.size !== rindex.length) { - /* if true, there was a duplicate in the keys */ - throw new Error("duplicate label provided to KeyIndex"); - } - - this.index = index; - this.rindex = rindex; - - this.getOffset = function getOffset(label: LabelType) { - const offset = index.get(label); - if (offset === undefined) return -1; - return offset; - }; - - this.getLabel = function getLabel(offset: number) { - return Number.isInteger(offset) ? rindex[offset] : undefined; - }; - } - - labels(): LabelArray { - return this.rindex; - } - - size(): number { - return this.rindex.length; - } - - subset(labels: (string | number)[]): LabelIndexBase { - /* validate subset */ - for (let i = 0, l = labels.length; i < l; i += 1) { - const label = labels[i]; - const offset = this.getOffset(label); - if (offset === undefined || offset === -1) { - throw new RangeError(`unknown label: ${label}`); - } - } - - return new KeyIndex(labels); - } - - isubset(offsets: OffsetArray): LabelIndexBase { - const { rindex } = this; - const maxOffset = rindex.length; - const labels = new Array(offsets.length); - for (let i = 0, l = offsets.length; i < l; i += 1) { - const offset = offsets[i]; - if (offset < 0 || offset >= maxOffset) - throw new RangeError(`out of bounds offset: ${offset}`); - labels[i] = rindex[offset]; - } - - return new KeyIndex(labels); - } - - isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase { - const { rindex } = this; - if (mask.length !== rindex.length) - throw new RangeError("mask has invalid length for index"); - let labels = new Array(mask.length); - let count = 0; - for (let i = 0, l = mask.length; i < l; i += 1) { - if (mask[i]) { - labels[count] = rindex[i]; - count += 1; - } - } - labels = labels.slice(0, count); - return new KeyIndex(labels); - } - - withLabel(label: LabelType): LabelIndexBase { - return new KeyIndex([...this.rindex, label]); - } - - withLabels(labels: LabelArray): LabelIndexBase { - return new KeyIndex([...this.rindex, ...labels]); - } - - dropLabel(label: LabelType): LabelIndexBase { - const idx = this.rindex.indexOf(label); - const labelArray = [...this.rindex]; - labelArray.splice(idx, 1); - return new KeyIndex(labelArray); - } -} - -export type LabelIndex = LabelIndexBase; - -export function isLabelIndex(i: unknown): i is LabelIndex { - return ( - i instanceof LabelIndexBase || - i instanceof IdentityInt32Index || - i instanceof DenseInt32Index || - i instanceof KeyIndex - ); -} - -/** @internal */ -function extent(tarr: GenericLabelArray): [number, number] { - let min = 0x7fffffff; - let max = ~min; // eslint-disable-line no-bitwise -- Establishes 0 of same size - for (let i = 0, l = tarr.length; i < l; i += 1) { - const v = tarr[i]; - if (v < min) { - min = v; - } - if (v > max) { - max = v; - } - } - return [min, max]; -} - -/* eslint-enable max-classes-per-file -- enable*/ diff --git a/client/src/util/dataframe/summarize.js b/client/src/util/dataframe/summarize.js new file mode 100644 index 00000000..b794c286 --- /dev/null +++ b/client/src/util/dataframe/summarize.js @@ -0,0 +1,85 @@ +/* +Private dataframe support functions + +TODO / XXX: for scalar/continuous data, this uses a naive method +of computing quantiles. Would be good to switch from sort to +partition at some point. +*/ + +import quantile from "../quantile"; +import { sortArray } from "../typedCrossfilter/sort"; + +// [ 0, 0.01, 0.02, ..., 1.0] +const centileNames = new Array(101).fill(0).map((v, idx) => idx / 100); + +export function summarizeContinuous(col) { + let min; + let max; + let nan = 0; + let pinf = 0; + let ninf = 0; + let percentiles; + if (col) { + // -Inf < finite < Inf < NaN + const sortedCol = sortArray(new col.constructor(col)); + + // count non-finites, which are at each end of sorted data + for (let i = sortedCol.length - 1; i >= 0; i -= 1) { + if (!Number.isNaN(sortedCol[i])) { + nan = sortedCol.length - i - 1; + break; + } + } + for (let i = 0, l = sortedCol.length; i < l; i += 1) { + if (sortedCol[i] !== Number.NEGATIVE_INFINITY) { + ninf = i; + break; + } + } + for (let i = sortedCol.length - nan - 1; i >= 0; i -= 1) { + if (sortedCol[i] !== Number.POSITIVE_INFINITY) { + pinf = sortedCol.length - i - nan - 1; + break; + } + } + + // compute percentiles on finite data ONLY + const sortedColFiniteOnly = sortedCol.slice( + ninf, + sortedCol.length - nan - pinf + ); + percentiles = quantile(centileNames, sortedColFiniteOnly, true); + min = percentiles[0]; + max = percentiles[100]; + } + return { + categorical: false, + min, + max, + nan, + pinf, + ninf, + percentiles, + }; +} + +export function summarizeCategorical(col) { + const categoryCounts = new Map(); + if (col) { + for (let r = 0, l = col.length; r < l; r += 1) { + const val = col[r]; + let curCount = categoryCounts.get(val); + if (curCount === undefined) curCount = 0; + categoryCounts.set(val, curCount + 1); + } + } + const sortedCategoryByCounts = new Map( + [...categoryCounts.entries()].sort((a, b) => b[1] - a[1]) + ); + return { + categorical: true, + categories: [...sortedCategoryByCounts.keys()], + categoryCounts: sortedCategoryByCounts, + numCategories: sortedCategoryByCounts.size, + }; +} diff --git a/client/src/util/dataframe/summarize.ts b/client/src/util/dataframe/summarize.ts deleted file mode 100644 index 22b38329..00000000 --- a/client/src/util/dataframe/summarize.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* -Private dataframe support functions - -TODO / XXX: for scalar/continuous data, this uses a naive method -of computing quantiles. Would be good to switch from sort to -partition at some point. -*/ -import { - AnyArray, - GenericArrayConstructor, -} from "../../common/types/arraytypes"; -import { ContinuousColumnSummary, CategoricalColumnSummary } from "./types"; -import quantile from "../quantile"; -import { sortArray } from "../typedCrossfilter/sort"; - -// [ 0, 0.01, 0.02, ..., 1.0] -const centileNames = new Array(101).fill(0).map((_v, idx) => idx / 100); - -export function summarizeContinuous(col: AnyArray): ContinuousColumnSummary { - let nan = 0; - let pinf = 0; - let ninf = 0; - - // -Inf < finite < Inf < NaN - const sortedCol = sortArray( - new (col.constructor as GenericArrayConstructor)(col) - ); - - // count non-finites, which are at each end of sorted data - for (let i = sortedCol.length - 1; i >= 0; i -= 1) { - if (!Number.isNaN(sortedCol[i])) { - nan = sortedCol.length - i - 1; - break; - } - } - for (let i = 0, l = sortedCol.length; i < l; i += 1) { - if (sortedCol[i] !== Number.NEGATIVE_INFINITY) { - ninf = i; - break; - } - } - for (let i = sortedCol.length - nan - 1; i >= 0; i -= 1) { - if (sortedCol[i] !== Number.POSITIVE_INFINITY) { - pinf = sortedCol.length - i - nan - 1; - break; - } - } - - // compute percentiles on finite data ONLY - const sortedColFiniteOnly = sortedCol.slice( - ninf, - sortedCol.length - nan - pinf - ); - const percentiles = quantile(centileNames, sortedColFiniteOnly, true); - const min = percentiles[0]; - const max = percentiles[100]; - - return { - categorical: false, - min, - max, - nan, - pinf, - ninf, - percentiles, - }; -} - -export function summarizeCategorical(col: AnyArray): CategoricalColumnSummary { - const categoryCounts = new Map(); - if (col) { - for (let r = 0, l = col.length; r < l; r += 1) { - const val = col[r]; - let curCount = categoryCounts.get(val); - if (curCount === undefined) curCount = 0; - categoryCounts.set(val, curCount + 1); - } - } - const sortedCategoryByCounts = new Map( - [...categoryCounts.entries()].sort((a, b) => b[1] - a[1]) - ); - return { - categorical: true, - categories: [...sortedCategoryByCounts.keys()], - categoryCounts: sortedCategoryByCounts, - numCategories: sortedCategoryByCounts.size, - }; -} diff --git a/client/src/util/dataframe/types.ts b/client/src/util/dataframe/types.ts deleted file mode 100644 index 5b3b0bc7..00000000 --- a/client/src/util/dataframe/types.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { TypedArray } from "../../common/types/arraytypes"; - -export type LabelType = number | string; - -type CommonProps = { - [K in keyof A & keyof B]: A[K] | B[K]; -}; -export type GenericLabelArray = CommonProps, Int32Array>; -export type LabelArray = GenericLabelArray; - -export type OffsetType = number; -export type OffsetArray = - | Int8Array - | Uint8Array - | Int16Array - | Uint16Array - | Int32Array - | Uint32Array - | number[]; - -export type ContinuousColumnSummary = { - categorical: false; - min: number; - max: number; - nan: number; - pinf: number; - ninf: number; - percentiles: number[]; -}; - -export type CategoricalColumnSummary = { - categorical: true; - categories: (number | string | boolean)[]; - categoryCounts: Map; - numCategories: number; -}; - -export type ColumnSummary = ContinuousColumnSummary | CategoricalColumnSummary; - -export type ContinuousHistogram = number[]; -export type ContinuousHistogramBy = Map; -export type CategoricalHistogram = Map; -export type CategoricalHistogramBy = Map; - -export type DataframeValue = number | string | boolean; - -export type DataframeValueArray = DataframeValue[] | TypedArray; - -export type DataframeColumnGetter = ( - label: LabelType -) => DataframeValue | undefined; - -/** - * Interface representing a Dataframe column. Eg, returned by - * Dataframe.col(). - */ -export interface DataframeColumn extends DataframeColumnGetter { - /** - * __id is unique per Dataframe and DataframeColumn, and is used as a memoization key. - */ - readonly __id: string; - - /** - * Boolean indicating if the underlying data supports continuous operations, eg, - * summarizeContinuous. - */ - isContinuous: boolean; - - /** - * Return underlying column data as an array-like object. - */ - asArray: () => DataframeValueArray; - - /** - * Continuous data summary. Will throw if !isContinuous. - */ - summarizeContinuous: () => ContinuousColumnSummary; - - /** - * Categorical data summary. - */ - summarizeCategorical: () => CategoricalColumnSummary; - - /** - * Continuous bin/histogram. Will throw if !isContinuous. - * @param bins - array of bin boundary fractions, in range [0., 1.] - * @param domain - data domain [min, max] - */ - histogramContinuous: ( - bins: number, - domain: [number, number] - ) => ContinuousHistogram; - - /** - * Continuous bin/histogram, grouped by another categorical column. Will throw if !isContinuous. - * @param bins - array of bin boundary fractions, in range [0., 1.] - * @param domain - data domain [min, max] - * @param by - group by categorical column - */ - histogramContinuousBy: ( - bins: number, - domain: [number, number], - by: DataframeColumn - ) => ContinuousHistogramBy; - - /** - * Categorical bin/histogram. - */ - histogramCategorical: () => CategoricalHistogram; - - /** - * Categorical bin/histogram grouped by another column. - * @param by - group by categorical column - */ - histogramCategoricalBy: (by: DataframeColumn) => CategoricalHistogramBy; - - /** - * Return true if the column contains the row label. - */ - has: (rlabel: LabelType) => boolean; - - /** - * Return true if the column contains the row offset. Identical to - * (offset >= 0 && offset < dataframe.length) - */ - ihas: (offset: OffsetType) => boolean; - - /** - * Return index of the value, as a _label_. Returns undefined if - * not present. *NOTE*: unlike Array.indexOf, does not return an - * offset. - */ - indexOf: (value: DataframeValue) => LabelType | undefined; - - /** - * Return the value at the given offset, or undefined if not present. - */ - iget: (offset: OffsetType) => DataframeValue | undefined; -} diff --git a/client/src/util/dataframe/util.ts b/client/src/util/dataframe/util.js similarity index 57% rename from client/src/util/dataframe/util.ts rename to client/src/util/dataframe/util.js index 64b6a112..aa00e0c8 100644 --- a/client/src/util/dataframe/util.ts +++ b/client/src/util/dataframe/util.js @@ -2,19 +2,18 @@ Private utility code for dataframe */ -export function callOnceLazy< - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- a legitimate use of any. - T extends (...args: any[]) => any = (...args: any[]) => any ->(fn: T): (...args: Parameters) => ReturnType { +export { isTypedArray, isArrayOrTypedArray } from "../typeHelpers"; + +export function callOnceLazy(f) { /* call function once, and save the result, regardless of arguments (this is not the same as typical memoization). */ - let value: ReturnType; + let value; let calledOnce = false; - const result = function result(...args: Parameters): ReturnType { + const result = function result(...args) { if (!calledOnce) { - value = fn(...args); + value = f(...args); calledOnce = true; } return value; @@ -22,14 +21,7 @@ export function callOnceLazy< return result; } -export function memoize< - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- a legitimate use of any. - T extends (...args: any[]) => any = (...args: any[]) => any ->( - fn: T, - hashFn: (...args: Parameters) => string, - maxResultsCached = -1 -): (...args: Parameters) => ReturnType { +export function memoize(fn, hashFn, maxResultsCached = -1) { /* function memoization, with user-provided hash. hashFn must return a key which will be unique as a Map key (ie, obeys "sameValueZero" algorithm @@ -37,7 +29,7 @@ export function memoize< https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality */ const cache = new Map(); - const wrap = function wrap(...args: Parameters): ReturnType { + const wrap = function wrap(...args) { const key = hashFn(...args); if (cache.has(key)) { return cache.get(key); @@ -62,11 +54,11 @@ export function memoize< } /** - *memoization helpers - just a global counter. - */ +memoization helpers - just a global counter. +**/ let __DataframeMemoId__ = 0; -export function __getMemoId(): string { +export function __getMemoId() { const id = __DataframeMemoId__; __DataframeMemoId__ += 1; - return id.toString(); + return id; } diff --git a/client/src/util/finiteExtent.ts b/client/src/util/finiteExtent.js similarity index 52% rename from client/src/util/finiteExtent.ts rename to client/src/util/finiteExtent.js index d778aa01..24239113 100644 --- a/client/src/util/finiteExtent.ts +++ b/client/src/util/finiteExtent.js @@ -6,11 +6,7 @@ If undefined or empty array, or array contains only non-finite numbers, will return [undefined, undefined] */ -import type { TypedArray } from "../common/types/arraytypes"; - -function finiteExtent( - tarr: TypedArray -): [number, number] | [undefined, undefined] { +function finiteExtent(tarr) { let min; let max; let i; @@ -24,17 +20,14 @@ function finiteExtent( break; } } - if (min !== undefined && max !== undefined) { - for (; i < tarr.length; i += 1) { - const val = tarr[i]; - if (Number.isFinite(val)) { - if (min > val) min = val; - if (max < val) max = val; - } + for (; i < tarr.length; i += 1) { + const val = tarr[i]; + if (Number.isFinite(val)) { + if (min > val) min = val; + if (max < val) max = val; } - return [min, max]; } - return [undefined, undefined]; + return [min, max]; } export default finiteExtent; diff --git a/client/src/util/fromEntries.js b/client/src/util/fromEntries.js new file mode 100644 index 00000000..747c8e2f --- /dev/null +++ b/client/src/util/fromEntries.js @@ -0,0 +1,13 @@ +export default function fromEntries(arr) { + /* + Similar to Object.fromEntries, but only handles array. + This could be replaced with the standard fucnction once it + is widely available. As of 3/20/2019, it has not yet + been released in the Chrome stable channel. + */ + const obj = {}; + for (let i = 0, l = arr.length; i < l; i += 1) { + obj[arr[i][0]] = arr[i][1]; + } + return obj; +} diff --git a/client/src/util/fromEntries.ts b/client/src/util/fromEntries.ts deleted file mode 100644 index c961597f..00000000 --- a/client/src/util/fromEntries.ts +++ /dev/null @@ -1,17 +0,0 @@ -export default function fromEntries( - arr: [string | number, T][] -): { [key: string]: T } { - /* - Similar to Object.fromEntries, but only handles array. - This could be replaced with the standard function once it - is widely available. As of 3/20/2019, it has not yet - been released in the Chrome stable channel. - */ - const obj: { [key: string]: T } = {}; - - for (let i = 0; i < arr.length; i += 1) { - obj[arr[i][0]] = arr[i][1]; - } - - return obj; -} diff --git a/client/src/util/glHelpers.ts b/client/src/util/glHelpers.js similarity index 100% rename from client/src/util/glHelpers.ts rename to client/src/util/glHelpers.js diff --git a/client/src/util/maybeScientific.ts b/client/src/util/maybeScientific.js similarity index 77% rename from client/src/util/maybeScientific.ts rename to client/src/util/maybeScientific.js index 8f701c45..234f49e1 100644 --- a/client/src/util/maybeScientific.ts +++ b/client/src/util/maybeScientific.js @@ -1,4 +1,3 @@ -import { ScaleLinear } from "d3"; import significantDigits from "./significantDigits"; /** @@ -11,14 +10,12 @@ import significantDigits from "./significantDigits"; * @returns - the number formatted as scientific, if it's big enough */ -export default function maybeScientific( - x: ScaleLinear -): string { +export default function maybeScientific(x) { let format = ","; const _ticks = x.ticks(4); - if (x.domain().some((n: number) => Math.abs(n) >= 10000)) { - /* + if (x.domain().some((n) => Math.abs(n) >= 10000)) { + /* heuristic: if the last tick d3 wants to render has one significant digit ie., 2000, render 2e+3, but if it's anything else ie., 42000000 render 4.20e+n diff --git a/client/src/util/nameCreators.ts b/client/src/util/nameCreators.js similarity index 64% rename from client/src/util/nameCreators.ts rename to client/src/util/nameCreators.js index f308e79c..415e30ac 100644 --- a/client/src/util/nameCreators.ts +++ b/client/src/util/nameCreators.js @@ -13,40 +13,29 @@ anno matrix namespaces. It is still used by the component tier. */ -const makeDimensionName = (namespace: string, key: string): string => - `${namespace}_${key}`; +const makeDimensionName = (namespace, key) => `${namespace}_${key}`; -export const layoutDimensionName = (key: string): string => - makeDimensionName("layout", key); - -export const obsAnnoDimensionName = (key: string): string => - makeDimensionName("obsAnno", key); - -export const diffexpDimensionName = (key: string): string => +export const layoutDimensionName = (key) => makeDimensionName("layout", key); +export const obsAnnoDimensionName = (key) => makeDimensionName("obsAnno", key); +export const diffexpDimensionName = (key) => makeDimensionName("varData_diffexp", key); - -export const userDefinedDimensionName = (key: string): string => +export const userDefinedDimensionName = (key) => makeDimensionName("varData_userDefined", key); - -export const geneSetSummaryDimensionName = (key: string): string => +export const geneSetSummaryDimensionName = (key) => makeDimensionName("geneSetSummary", key); -export interface ContinuousNamespace { - isObs?: boolean; - isDiffExp?: boolean; - isUserDefined?: boolean; - isGeneSetSummary?: boolean; -} - /* + continuousNamespace = { + isObs: true, + isDiffExp: false, + isUserDefined: false, + isGeneSet: false, + } ie., makeContinuousDimensionName(continuousNamespace = {isObs: true}, "total_reads") see: histogram brush, as it doesn't know what type of continuous it was with only field */ -export const makeContinuousDimensionName = ( - continuousNamespace: ContinuousNamespace, - key: string -): string => { +export const makeContinuousDimensionName = (continuousNamespace, key) => { let name; if (continuousNamespace.isObs) { name = obsAnnoDimensionName(key); diff --git a/client/src/util/parseBulkGeneString.ts b/client/src/util/parseBulkGeneString.js similarity index 78% rename from client/src/util/parseBulkGeneString.ts rename to client/src/util/parseBulkGeneString.js index 33b24625..015c4e88 100644 --- a/client/src/util/parseBulkGeneString.ts +++ b/client/src/util/parseBulkGeneString.js @@ -6,6 +6,6 @@ import pull from "lodash.pull"; import uniq from "lodash.uniq"; -export default function parseBulkGeneString(geneString: string): Array { +export default function parseBulkGeneString(geneString) { return pull(uniq(geneString.split(/[ ,]+/)), ""); } diff --git a/client/src/util/parseRGB.ts b/client/src/util/parseRGB.js similarity index 72% rename from client/src/util/parseRGB.ts rename to client/src/util/parseRGB.js index be1e2648..d8546d87 100644 --- a/client/src/util/parseRGB.ts +++ b/client/src/util/parseRGB.js @@ -4,16 +4,14 @@ import scaleRGB from "./scaleRGB"; // to do this operation. This lets us have speed, but keep the pleasant ability // to talk about colors by their text description eg, 'rgb(0,0,1)' // -const colorCache = {} as { [key: string]: [number, number, number] }; +const colorCache = {}; -function parseColorName(c: string): [number, number, number] { +function parseColorName(c) { if (c[0] !== "#") { const _c = c.replace(/[^\d,.]/g, "").split(","); return [scaleRGB(+_c[0]), scaleRGB(+_c[1]), scaleRGB(+_c[2])]; } const parsedHex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c); - if (!parsedHex || parsedHex.length < 4) - throw new Error(`Invalid hex color: ${c}`); return [ scaleRGB(parseInt(parsedHex[1], 16)), scaleRGB(parseInt(parsedHex[2], 16)), @@ -21,7 +19,7 @@ function parseColorName(c: string): [number, number, number] { ]; } -export default (c: string): [number, number, number] => { +export default (c) => { let cv = colorCache[c]; if (!cv) { cv = parseColorName(c); diff --git a/client/src/util/promiseLimit.ts b/client/src/util/promiseLimit.js similarity index 64% rename from client/src/util/promiseLimit.ts rename to client/src/util/promiseLimit.js index eb928fb4..dde85bd8 100644 --- a/client/src/util/promiseLimit.ts +++ b/client/src/util/promiseLimit.js @@ -28,55 +28,28 @@ Priority is a numeric value. Lower first. Stable ordering. import TinyQueue from "tinyqueue"; -function compare( - a: PromiseLimitQueueItem, - b: PromiseLimitQueueItem -): number { +function compare(a, b) { const diff = a.priority - b.priority; if (diff) return diff; return a.order - b.order; } -interface PromiseLimitQueueItem { - priority: number; - order: number; - resolve: (value: T | PromiseLike) => void; - reject: (reason?: unknown) => void; - fn: (...args: Array) => Promise; - args: Array; -} - -export default class PromiseLimit { - queue: TinyQueue>; - - maxConcurrency: number; - - pending: number; - - insertCounter: number; - +export default class PromiseLimit { constructor(maxConcurrency = 5) { - this.queue = new TinyQueue>( - new Array>(), - compare - ); + this.queue = new TinyQueue([], compare); this.maxConcurrency = maxConcurrency; this.pending = 0; this.insertCounter = 0; } - priorityAdd( - p: number, - fn: () => Promise, - ...args: Array - ): Promise { + priorityAdd(p, fn, ...args) { // p - numermic priority (lower first) // fn - must return a promise // args - will be passed to fn return this._push(p, fn, args); } - add(fn: () => Promise, ...args: Array): Promise { + add(fn, ...args) { // fn - must return a promise // args - will be passed to fn return this._push(0, fn, args); @@ -86,24 +59,20 @@ export default class PromiseLimit { Private below **/ - _push( - priority: number, - fn: () => Promise, - args: Array - ): Promise { - const order = this.insertCounter; - this.insertCounter += 1; + _push(priority, fn, args) { + const order = this.insertCount; + this.insertCount += 1; return new Promise((resolve, reject) => { this.queue.push({ priority, order, fn, args, resolve, reject }); this._resolveNext(false); }); } - _resolveNext = (completed = true): void => { + _resolveNext = (completed = true) => { if (completed) this.pending -= 1; while (this.queue.length > 0 && this.pending < this.maxConcurrency) { - const task = this.queue.pop() as PromiseLimitQueueItem; // order of insertion + const task = this.queue.pop(); // order of insertion this.pending += 1; const { resolve, reject, fn, args } = task; diff --git a/client/src/util/quantile.ts b/client/src/util/quantile.js similarity index 60% rename from client/src/util/quantile.ts rename to client/src/util/quantile.js index ee9d0ade..0dc528da 100644 --- a/client/src/util/quantile.ts +++ b/client/src/util/quantile.js @@ -12,25 +12,13 @@ Arguments: */ -import { NumberArray, TypedArrayConstructor } from "../common/types/arraytypes"; - import { sortArray } from "./typedCrossfilter/sort"; -export default function quantile( - quantArr: number[], - tarr: NumberArray, - sorted = false -): number[] { +export default function quantile(quantArr, tarr, sorted = false) { /* start with the naive (sort) implementation. Later, use a faster partition */ - - if (tarr.length === 0) { - return new Array(quantArr.length).fill(0); - } - - const Ctor: TypedArrayConstructor = tarr.constructor as TypedArrayConstructor; - const arr = sorted ? tarr : sortArray(new Ctor(tarr)); // copy + const arr = sorted ? tarr : sortArray(new tarr.constructor(tarr)); // copy const len = arr.length; return quantArr.map((q) => { if (q === 1) { diff --git a/client/src/util/range.ts b/client/src/util/range.js similarity index 64% rename from client/src/util/range.ts rename to client/src/util/range.js index 1562f151..3d43c8b3 100644 --- a/client/src/util/range.ts +++ b/client/src/util/range.js @@ -22,44 +22,29 @@ rangeFill(array, start, step) -> array */ -import { TypedArray, NumberArray } from "../common/types/arraytypes"; - -function _doFill( - arr: T, - start: number, - step: number, - count: number -): T { +function _doFill(arr, start, step, count) { for (let idx = 0, val = start; idx < count; idx += 1, val += step) { arr[idx] = val; } return arr; } -export function rangeFill(arr: NumberArray, start = 0, step = 1): NumberArray { +export function rangeFill(arr, start = 0, step = 1) { return _doFill(arr, start, step, arr.length); } -export function range( - start: number, - stop?: number, - step?: number -): Array { +export function range(start, stop, step) { if (start === undefined) return []; if (stop === undefined) { stop = start; start = 0; } - step = step || 1; // catch undefined and zero + step = step || 1; // catch undefind and zero const len = Math.max(Math.ceil((stop - start) / step), 0); return _doFill(new Array(len), start, step, len); } -export function linspace( - start: number, - stop: number, - nsteps: number -): Array { - const delta = (stop - start) / Number((nsteps - 1).toFixed()); +export function linspace(start, stop, nsteps) { + const delta = (stop - start) / (nsteps - 1).toFixed(); return range(0, nsteps, 1).map((i) => start + i * delta); } diff --git a/client/src/util/renderThrottle.js b/client/src/util/renderThrottle.js new file mode 100644 index 00000000..36c813c1 --- /dev/null +++ b/client/src/util/renderThrottle.js @@ -0,0 +1,17 @@ +export default function renderThrottle(callback) { + /* + This wraps a call to requestAnimationFrame(), enforcing a single + render callback at any given time (ie, you can call this any number + of times, and it will coallesce multiple inter-frame calls into a + single render). + */ + let rafCurrentlyInProgress = null; + return function f() { + if (rafCurrentlyInProgress) return; + const context = this; + rafCurrentlyInProgress = window.requestAnimationFrame(() => { + callback.apply(context); + rafCurrentlyInProgress = null; + }); + }; +} diff --git a/client/src/util/renderThrottle.ts b/client/src/util/renderThrottle.ts deleted file mode 100644 index ea97d01e..00000000 --- a/client/src/util/renderThrottle.ts +++ /dev/null @@ -1,18 +0,0 @@ -export default function renderThrottle( - callback: (this: T) => void -): (this: T) => void { - /* - This wraps a call to requestAnimationFrame(), enforcing a single - render callback at any given time (ie, you can call this any number - of times, and it will coallesce multiple inter-frame calls into a - single render). - */ - let rafCurrentlyInProgress: number | null = null; - return function f(this: T) { - if (rafCurrentlyInProgress) return; // eslint-disable-next-line @typescript-eslint/no-this-alias --- required for functionality - rafCurrentlyInProgress = window.requestAnimationFrame(() => { - callback.call(this); - rafCurrentlyInProgress = null; - }); - }; -} diff --git a/client/src/util/scaleLinear.ts b/client/src/util/scaleLinear.js similarity index 65% rename from client/src/util/scaleLinear.ts rename to client/src/util/scaleLinear.js index 1e9dd494..239a5dc0 100644 --- a/client/src/util/scaleLinear.ts +++ b/client/src/util/scaleLinear.js @@ -6,18 +6,15 @@ // myScale(0) === -1 // this is is equivalent to d3.scaleLinear().domain([0,1]).range([-1,1]) -export default ( - domain: [number, number], - range: [number, number] -): ((value: number) => number) => { +export default (domain, range) => { const domainStart = domain[0]; const scale = (range[1] - range[0]) / (domain[1] - domain[0]); const invScale = 1 / scale; const rangeStart = range[0]; - const f = (value: number) => (value - domainStart) * scale + rangeStart; + const f = (value) => (value - domainStart) * scale + rangeStart; // inverter - f.invert = (value: number) => (value - rangeStart) * invScale + domainStart; + f.invert = (value) => (value - rangeStart) * invScale + domainStart; return f; }; diff --git a/client/src/util/scaleRGB.ts b/client/src/util/scaleRGB.js similarity index 83% rename from client/src/util/scaleRGB.ts rename to client/src/util/scaleRGB.js index 5c065dba..10b42d35 100644 --- a/client/src/util/scaleRGB.ts +++ b/client/src/util/scaleRGB.js @@ -1,4 +1,4 @@ -export default (input: number): number => { +export default (input) => { const outputMax = 1; const outputMin = 0; diff --git a/client/src/util/significantDigits.ts b/client/src/util/significantDigits.js similarity index 66% rename from client/src/util/significantDigits.ts rename to client/src/util/significantDigits.js index 287d65f1..87b032d2 100644 --- a/client/src/util/significantDigits.ts +++ b/client/src/util/significantDigits.js @@ -1,11 +1,8 @@ -/* +/* via https://github.com/nodef/extra-number/blob/master/scripts/significantDigits.js */ -const significantDigits = (n: number): number => - n +export default (n) => n .toExponential() .replace(/e[+\-0-9]*$/, "") .replace(/^0\.?0*|\./, "").length; - -export default significantDigits; diff --git a/client/src/util/stateManager/annotationsHelpers.ts b/client/src/util/stateManager/annotationsHelpers.js similarity index 71% rename from client/src/util/stateManager/annotationsHelpers.ts rename to client/src/util/stateManager/annotationsHelpers.js index 4ce35ffe..999ee961 100644 --- a/client/src/util/stateManager/annotationsHelpers.ts +++ b/client/src/util/stateManager/annotationsHelpers.js @@ -3,9 +3,6 @@ Helper functions for user-editable annotations state management. See also reducers/annotations.js */ -import { Schema } from "../../common/types/schema"; -import { Dataframe, LabelType } from "../dataframe"; - /* There are a number of state constraints assumed throughout the application: @@ -19,51 +16,37 @@ application: In addition, the current state management only allows for categorical annotations to be writable. */ -export function isCategoricalAnnotation( - schema: Schema, - name: string -): boolean | undefined { - /* + +export function isCategoricalAnnotation(schema, name) { + /* we treat any string, categorical or boolean as a categorical. + Return true/false/undefined (for unkonwn fields) */ const colSchema = schema.annotations.obsByName[name]; - if (colSchema === undefined) return undefined; - const { type } = colSchema; - return type === "string" || type === "boolean" || type === "categorical"; } -export function isContinuousAnnotation( - schema: Schema, - name: string -): boolean | undefined { +export function isContinuousAnnotation(schema, name) { + /* + Return true/false/undefined + */ const colSchema = schema.annotations.obsByName[name]; - if (colSchema === undefined) return undefined; - const { type } = colSchema; - return !(type === "string" || type === "boolean" || type === "categorical"); } -function _isUserAnnotation(schema: Schema, name: string): boolean { +function _isUserAnnotation(schema, name) { return schema.annotations.obsByName[name]?.writable || false; } -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. export function isUserAnnotation(annoMatrix, name) { return _isUserAnnotation(annoMatrix.schema, name); } -export function allHaveLabelByMask( - df: Dataframe, - colName: LabelType, - label: string, - mask: Uint8Array -): boolean { +export function allHaveLabelByMask(df, colName, label, mask) { // return true if all rows as indicated by mask have the colname set to label. // False if not. const col = df.col(colName); @@ -80,8 +63,7 @@ export function allHaveLabelByMask( } const legalCharacters = /^(\w|[ .()-])+$/; - -export function annotationNameIsErroneous(name: string): boolean | string { +export function annotationNameIsErroneous(name) { /* Validate the name - return: * false - a valid name @@ -108,6 +90,6 @@ export function annotationNameIsErroneous(name: string): boolean | string { } } - /* all is well! Indicate not erroneous with a false */ + /* all is well! Indicte not erroneous with a false */ return false; } diff --git a/client/src/util/stateManager/colorHelpers.ts b/client/src/util/stateManager/colorHelpers.js similarity index 54% rename from client/src/util/stateManager/colorHelpers.ts rename to client/src/util/stateManager/colorHelpers.js index 62e19943..42a20374 100644 --- a/client/src/util/stateManager/colorHelpers.ts +++ b/client/src/util/stateManager/colorHelpers.js @@ -7,23 +7,12 @@ import memoize from "memoize-one"; import * as globals from "../../globals"; import parseRGB from "../parseRGB"; import { range } from "../range"; -import { Dataframe, LabelType } from "../dataframe"; /* given a color mode & accessor, generate an annoMatrix query that will fulfill it */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export function createColorQuery( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorMode: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - colorByAccessor: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - schema: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - genesets: any -) { +export function createColorQuery(colorMode, colorByAccessor, schema, genesets) { if (!colorMode || !colorByAccessor || !schema || !genesets) return null; switch (colorMode) { @@ -72,8 +61,7 @@ export function createColorQuery( } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function _defaultColors(nObs: any) { +function _defaultColors(nObs) { const defaultCellColor = parseRGB(globals.defaultCellColor); return { rgb: new Array(nObs).fill(defaultCellColor), @@ -96,40 +84,33 @@ Returns: } */ function _createColorTable( - colorMode: string | null, - colorByAccessor: LabelType | null, - colorByData: Dataframe | null, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any, + colorMode, + colorByAccessor, + colorByData, + schema, userColors = null ) { - if (colorMode === null || colorByData === null) - return defaultColors(schema.dataframe.nObs); - switch (colorMode) { case "color by categorical metadata": { - if (colorByAccessor === null) return defaultColors(schema.dataframe.nObs); const data = colorByData.col(colorByAccessor).asArray(); - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. if (userColors && colorByAccessor in userColors) { return createUserColors(data, colorByAccessor, schema, userColors); } return createColorsByCategoricalMetadata(data, colorByAccessor, schema); } case "color by continuous metadata": { - if (colorByAccessor === null) return defaultColors(schema.dataframe.nObs); const col = colorByData.col(colorByAccessor); - const { min, max } = col.summarizeContinuous(); + const { min, max } = col.summarize(); return createColorsByContinuousMetadata(col.asArray(), min, max); } case "color by expression": { const col = colorByData.icol(0); - const { min, max } = col.summarizeContinuous(); + const { min, max } = col.summarize(); return createColorsByContinuousMetadata(col.asArray(), min, max); } case "color by geneset mean expression": { const col = colorByData.icol(0); - const { min, max } = col.summarizeContinuous(); + const { min, max } = col.summarize(); return createColorsByContinuousMetadata(col.asArray(), min, max); } default: { @@ -145,40 +126,25 @@ export const createColorTable = memoize(_createColorTable); * - scale: function which given label returns d3 color scale for label * Order doesn't matter - everything is keyed by label value. */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function loadUserColorConfig(userColors: any) { +export function loadUserColorConfig(userColors) { const convertedUserColors = {}; Object.keys(userColors).forEach((category) => { const [colors, scaleMap] = Object.keys(userColors[category]).reduce( (acc, label) => { const color = parseRGB(userColors[category][label]); - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message acc[0][label] = color; - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message acc[1][label] = d3.rgb(255 * color[0], 255 * color[1], 255 * color[2]); return acc; }, [{}, {}] ); - // @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const scale = (label: any) => scaleMap[label]; - // @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 scale = (label) => scaleMap[label]; convertedUserColors[category] = { colors, scale }; }); return convertedUserColors; } -function _createUserColors( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - data: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorAccessor: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - userColors: any -) { +function _createUserColors(data, colorAccessor, schema, userColors) { const { colors, scale: scaleByLabel } = userColors[colorAccessor]; const rgb = createRgbArray(data, colors); @@ -186,23 +152,14 @@ function _createUserColors( // See createColorsByCategoricalMetadata() for another example. const { categories } = schema.annotations.obsByName[colorAccessor]; const categoryMap = new Map(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categories.forEach((label: any, idx: any) => categoryMap.set(idx, label)); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const scale = (idx: any) => scaleByLabel(categoryMap.get(idx)); + categories.forEach((label, idx) => categoryMap.set(idx, label)); + const scale = (idx) => scaleByLabel(categoryMap.get(idx)); return { rgb, scale }; } const createUserColors = memoize(_createUserColors); -function _createColorsByCategoricalMetadata( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - data: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - colorAccessor: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - schema: any -) { +function _createColorsByCategoricalMetadata(data, colorAccessor, schema) { const { categories } = schema.annotations.obsByName[colorAccessor]; const scale = d3 @@ -210,8 +167,7 @@ function _createColorsByCategoricalMetadata( .domain([0, categories.length]); /* pre-create colors - much faster than doing it for each obs */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - const colors = categories.reduce((acc: any, cat: any, idx: any) => { + const colors = categories.reduce((acc, cat, idx) => { acc[cat] = parseRGB(scale(idx)); return acc; }, {}); @@ -223,8 +179,7 @@ const createColorsByCategoricalMetadata = memoize( _createColorsByCategoricalMetadata ); -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function createRgbArray(data: any, colors: any) { +function createRgbArray(data, colors) { const rgb = new Array(data.length); for (let i = 0, len = data.length; i < len; i += 1) { const label = data[i]; @@ -233,8 +188,7 @@ function createRgbArray(data: any, colors: any) { return rgb; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function _createColorsByContinuousMetadata(data: any, min: any, max: any) { +function _createColorsByContinuousMetadata(data, min, max) { const colorBins = 100; const scale = d3 .scaleQuantile() diff --git a/client/src/util/stateManager/controlsHelpers.ts b/client/src/util/stateManager/controlsHelpers.js similarity index 63% rename from client/src/util/stateManager/controlsHelpers.ts rename to client/src/util/stateManager/controlsHelpers.js index d4ce919e..d64de2b5 100644 --- a/client/src/util/stateManager/controlsHelpers.ts +++ b/client/src/util/stateManager/controlsHelpers.js @@ -30,9 +30,7 @@ Remember that option values can be ANY js type, except undefined/null. } } */ - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function isSelectableCategoryName(schema: any, name: any) { +export function isSelectableCategoryName(schema, name) { const { index } = schema.annotations.obs; const colSchema = schema.annotations.obsByName[name]; return ( @@ -42,8 +40,7 @@ export function isSelectableCategoryName(schema: any, name: any) { ); } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function selectableCategoryNames(schema: any, names: any) { +export function selectableCategoryNames(schema, names) { /* return all obs annotation names that are categorical AND have a "reasonably" small number of categories AND are not the index column. @@ -51,14 +48,11 @@ export function selectableCategoryNames(schema: any, names: any) { If the initial name list not provided, use everything in the schema. */ if (!schema) return []; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - if (!names) names = schema.annotations.obs.columns.map((c: any) => c.name); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - return names.filter((name: any) => isSelectableCategoryName(schema, name)); + if (!names) names = schema.annotations.obs.columns.map((c) => c.name); + return names.filter((name) => isSelectableCategoryName(schema, name)); } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function createCategorySummaryFromDfCol(dfCol: any, colSchema: any) { +export function createCategorySummaryFromDfCol(dfCol, colSchema) { const { writable: isUserAnno } = colSchema; /* @@ -70,13 +64,9 @@ export function createCategorySummaryFromDfCol(dfCol: any, colSchema: any) { const { categories: allCategoryValues } = colSchema; const categoryValues = allCategoryValues; const categoryValueCounts = allCategoryValues.map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - (cat: any) => summary.categoryCounts.get(cat) ?? 0 - ); - const categoryValueIndices = new Map( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - categoryValues.map((v: any, i: any) => [v, i]) + (cat) => summary.categoryCounts.get(cat) ?? 0 ); + const categoryValueIndices = new Map(categoryValues.map((v, i) => [v, i])); const numCategoryValues = categoryValueIndices.size; return { @@ -89,14 +79,11 @@ export function createCategorySummaryFromDfCol(dfCol: any, colSchema: any) { }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function createCategoricalSelection(names: any) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - return fromEntries(names.map((name: any) => [name, new Map()])); +export function createCategoricalSelection(names) { + return fromEntries(names.map((name) => [name, new Map()])); } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function pruneVarDataCache(varData: any, needed: any) { +export function pruneVarDataCache(varData, needed) { /* Remove any unneeded columns from the varData dataframe. Will only prune / remove if the total column count exceeds VarDataCacheLowWatermark diff --git a/client/src/util/stateManager/index.ts b/client/src/util/stateManager/index.js similarity index 100% rename from client/src/util/stateManager/index.ts rename to client/src/util/stateManager/index.js diff --git a/client/src/util/stateManager/matrix.ts b/client/src/util/stateManager/matrix.js similarity index 81% rename from client/src/util/stateManager/matrix.ts rename to client/src/util/stateManager/matrix.js index a1ddb75c..52717157 100644 --- a/client/src/util/stateManager/matrix.ts +++ b/client/src/util/stateManager/matrix.js @@ -1,10 +1,6 @@ import { flatbuffers } from "flatbuffers"; import { NetEncoding } from "./matrix_generated"; -import { - TypedArray, - isTypedArray, - isFloatTypedArray, -} from "../../common/types/arraytypes"; +import { isTypedArray, isFpTypedArray } from "../typeHelpers"; import { Dataframe, IdentityInt32Index, @@ -21,14 +17,12 @@ Matrix flatbuffer decoding support. See fbs/matrix.fbs /* Decode NetEncoding.TypedArray */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function decodeTypedArray(uType: any, uValF: any, inplace = false) { +function decodeTypedArray(uType, uValF, inplace = false) { if (uType === NetEncoding.TypedArray.NONE) { return null; } // Convert to a JS class that supports this type - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. const TypeClass = NetEncoding[NetEncoding.TypedArray[uType]]; // Create a TypedArray that references the underlying buffer let arr = uValF(new TypeClass()).dataArray(); @@ -54,8 +48,7 @@ Returns: object containing decoded Matrix: colIdx: []|null } */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function decodeMatrixFBS(arrayBuffer: any, inplace = false) { +export function decodeMatrixFBS(arrayBuffer, inplace = false) { const bb = new flatbuffers.ByteBuffer(new Uint8Array(arrayBuffer)); const matrix = NetEncoding.Matrix.getRootAsMatrix(bb); @@ -86,11 +79,8 @@ export function decodeMatrixFBS(arrayBuffer: any, inplace = false) { }; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function encodeTypedArray(builder: any, uType: any, uData: any) { - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. +function encodeTypedArray(builder, uType, uData) { const uTypeName = NetEncoding.TypedArray[uType]; - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. const ArrayType = NetEncoding[uTypeName]; const dv = ArrayType.createDataVector(builder, uData); builder.startObject(1); @@ -98,18 +88,17 @@ function encodeTypedArray(builder: any, uType: any, uData: any) { return builder.endObject(); } -export function encodeMatrixFBS(df: Dataframe): Uint8Array { +export function encodeMatrixFBS(df) { /* encode the dataframe as an FBS Matrix */ /* row indexing not supported currently */ - if (!(df.rowIndex instanceof IdentityInt32Index)) { + if (df.rowIndex.constructor !== IdentityInt32Index) { throw new Error("FBS does not support row index encoding at this time"); } const shape = df.dims; - // @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1. const utf8Encoder = new TextEncoder("utf-8"); const builder = new flatbuffers.Builder(1024); @@ -124,7 +113,6 @@ export function encodeMatrixFBS(df: Dataframe): Uint8Array { let uType; let tarr; if (isTypedArray(carr)) { - // @ts-expect-error --- FIXME: Element implicitly has an 'any' type. uType = NetEncoding.TypedArray[carr.constructor.name]; tarr = encodeTypedArray(builder, uType, carr); } else { @@ -180,7 +168,7 @@ export function encodeMatrixFBS(df: Dataframe): Uint8Array { return builder.asUint8Array(); } -function promoteTypedArray(o: TypedArray) { +function promoteTypedArray(o) { /* Decide what internal data type to use for the data returned from the server. @@ -188,7 +176,7 @@ function promoteTypedArray(o: TypedArray) { TODO - future optimization: not all int32/uint32 data series require promotion to float64. We COULD simply look at the data to decide. */ - if (isFloatTypedArray(o) || Array.isArray(o)) return o; + if (isFpTypedArray(o) || Array.isArray(o)) return o; let TypedArrayCtor; switch (o.constructor) { @@ -212,9 +200,7 @@ function promoteTypedArray(o: TypedArray) { return new TypedArrayCtor(o); } -export function matrixFBSToDataframe( - arrayBuffers: ArrayBuffer | ArrayBuffer[] -): Dataframe { +export function matrixFBSToDataframe(arrayBuffers) { /* Convert array of Matrix FBS to a Dataframe. @@ -230,7 +216,7 @@ export function matrixFBSToDataframe( arrayBuffers = [arrayBuffers]; } if (arrayBuffers.length === 0) { - return Dataframe.empty(); + return Dataframe.Dataframe.empty(); } const fbs = arrayBuffers.map((ab) => decodeMatrixFBS(ab, true)); // leave in place @@ -243,7 +229,7 @@ export function matrixFBSToDataframe( const columns = fbs .map((fb) => fb.columns.map((c) => { - if (isFloatTypedArray(c) || Array.isArray(c)) return c; + if (isFpTypedArray(c) || Array.isArray(c)) return c; return promoteTypedArray(c); }) ) diff --git a/client/src/util/stateManager/matrix_generated.js b/client/src/util/stateManager/matrix_generated.js index 641865d8..8dc9ac95 100644 --- a/client/src/util/stateManager/matrix_generated.js +++ b/client/src/util/stateManager/matrix_generated.js @@ -648,9 +648,9 @@ NetEncoding.Column.getRootAsColumn = function (bb, obj) { NetEncoding.Column.prototype.uType = function () { var offset = this.bb.__offset(this.bb_pos, 4); return offset - ? /** @type {NetEncoding.TypedArray} */ (this.bb.readUint8( - this.bb_pos + offset - )) + ? /** @type {NetEncoding.TypedArray} */ ( + this.bb.readUint8(this.bb_pos + offset) + ) : NetEncoding.TypedArray.NONE; }; @@ -778,9 +778,9 @@ NetEncoding.Matrix.prototype.columnsLength = function () { NetEncoding.Matrix.prototype.colIndexType = function () { var offset = this.bb.__offset(this.bb_pos, 10); return offset - ? /** @type {NetEncoding.TypedArray} */ (this.bb.readUint8( - this.bb_pos + offset - )) + ? /** @type {NetEncoding.TypedArray} */ ( + this.bb.readUint8(this.bb_pos + offset) + ) : NetEncoding.TypedArray.NONE; }; @@ -799,9 +799,9 @@ NetEncoding.Matrix.prototype.colIndex = function (obj) { NetEncoding.Matrix.prototype.rowIndexType = function () { var offset = this.bb.__offset(this.bb_pos, 14); return offset - ? /** @type {NetEncoding.TypedArray} */ (this.bb.readUint8( - this.bb_pos + offset - )) + ? /** @type {NetEncoding.TypedArray} */ ( + this.bb.readUint8(this.bb_pos + offset) + ) : NetEncoding.TypedArray.NONE; }; diff --git a/client/src/util/stateManager/schemaHelpers.ts b/client/src/util/stateManager/schemaHelpers.js similarity index 62% rename from client/src/util/stateManager/schemaHelpers.ts rename to client/src/util/stateManager/schemaHelpers.js index 68c97f30..6a49b5ff 100644 --- a/client/src/util/stateManager/schemaHelpers.ts +++ b/client/src/util/stateManager/schemaHelpers.js @@ -8,13 +8,6 @@ import cloneDeep from "lodash.clonedeep"; import fromEntries from "../fromEntries"; import catLabelSort from "../catLabelSort"; -import { - RawSchema, - Schema, - EmbeddingSchema, - AnnotationColumnSchema, -} from "../../common/types/schema"; -import { LabelType } from "../dataframe/types"; /* System wide schema assumptions: @@ -22,25 +15,25 @@ System wide schema assumptions: - schema will be internally self-consistent (eg, index matches columns) */ -export function indexEntireSchema(schema: RawSchema): Schema { +export function indexEntireSchema(schema) { /* Index schema for ease of use */ - (schema as Schema).annotations.obsByName = fromEntries( - schema.annotations?.obs?.columns?.map((v) => [v.name, v]) || [] + schema.annotations.obsByName = fromEntries( + schema.annotations?.obs?.columns?.map((v) => [v.name, v]) ?? [] ); - (schema as Schema).annotations.varByName = fromEntries( - schema.annotations?.var?.columns?.map((v) => [v.name, v]) || [] + schema.annotations.varByName = fromEntries( + schema.annotations?.var?.columns?.map((v) => [v.name, v]) ?? [] ); - (schema as Schema).layout.obsByName = fromEntries( - schema.layout?.obs?.map((v) => [v.name, v]) || [] + schema.layout.obsByName = fromEntries( + schema.layout?.obs?.map((v) => [v.name, v]) ?? [] ); - (schema as Schema).layout.varByName = fromEntries( - schema.layout?.var?.map((v) => [v.name, v]) || [] + schema.layout.varByName = fromEntries( + schema.layout?.var?.map((v) => [v.name, v]) ?? [] ); - return schema as Schema; + return schema; } -function _copyObsAnno(schema: Schema): Schema { +function _copyObsAnno(schema) { /* redux copy conventions - WARNING, only for modifying obs annotations */ return { ...schema, @@ -51,7 +44,7 @@ function _copyObsAnno(schema: Schema): Schema { }; } -function _copyObsLayout(schema: Schema): Schema { +function _copyObsLayout(schema) { return { ...schema, layout: { @@ -61,7 +54,7 @@ function _copyObsLayout(schema: Schema): Schema { }; } -function _reindexObsAnno(schema: Schema): Schema { +function _reindexObsAnno(schema) { /* reindex obs annotations ONLY */ schema.annotations.obsByName = fromEntries( schema.annotations.obs.columns.map((v) => [v.name, v]) @@ -69,14 +62,14 @@ function _reindexObsAnno(schema: Schema): Schema { return schema; } -function _reindexObsLayout(schema: Schema) { +function _reindexObsLayout(schema) { schema.layout.obsByName = fromEntries( schema.layout.obs.map((v) => [v.name, v]) ); return schema; } -export function removeObsAnnoColumn(schema: Schema, name: LabelType): Schema { +export function removeObsAnnoColumn(schema, name) { const newSchema = _copyObsAnno(schema); newSchema.annotations.obs.columns = schema.annotations.obs.columns.filter( (v) => v.name !== name @@ -84,44 +77,29 @@ export function removeObsAnnoColumn(schema: Schema, name: LabelType): Schema { return _reindexObsAnno(newSchema); } -export function addObsAnnoColumn( - schema: Schema, - _: string, - defn: AnnotationColumnSchema -): Schema { +export function addObsAnnoColumn(schema, name, defn) { const newSchema = _copyObsAnno(schema); - newSchema.annotations.obs.columns.push(defn); - return _reindexObsAnno(newSchema); } -export function removeObsAnnoCategory( - schema: Schema, - name: LabelType, - category: string -): Schema { +export function removeObsAnnoCategory(schema, name, category) { /* remove a category from a categorical annotation */ const categories = schema.annotations.obsByName[name]?.categories; - - if (!categories) { + if (!categories) throw new Error("column does not exist or is not categorical"); - } const idx = categories.indexOf(category); - if (idx === -1) throw new Error("category does not exist"); const newSchema = _reindexObsAnno(_copyObsAnno(schema)); /* remove category. Do not need to resort as this can't change presentation order */ - newSchema.annotations.obsByName[name].categories?.splice(idx, 1); - + newSchema.annotations.obsByName[name].categories.splice(idx, 1); return newSchema; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function addObsAnnoCategory(schema: any, name: any, category: any) { +export function addObsAnnoCategory(schema, name, category) { /* add a category to a categorical annotation */ const categories = schema.annotations.obsByName[name]?.categories; if (!categories) @@ -134,27 +112,23 @@ export function addObsAnnoCategory(schema: any, name: any, category: any) { /* add category, retaining presentation sort order */ const catAnno = newSchema.annotations.obsByName[name]; - catAnno.categories = catLabelSort(catAnno.writable, [ - ...(catAnno.categories || []), + ...catAnno.categories, category, ]); - return newSchema; } -export function addObsLayout(schema: Schema, layout: EmbeddingSchema): Schema { +export function addObsLayout(schema, layout) { /* add or replace a layout */ const newSchema = _copyObsLayout(schema); newSchema.layout.obs.push(layout); return _reindexObsLayout(newSchema); } -export function removeObsLayout(schema: Schema, name: string): Schema { +export function removeObsLayout(schema, name) { /* remove a layout */ const newSchema = _copyObsLayout(schema); - newSchema.layout.obs = schema.layout.obs.filter((v) => v.name !== name); - return _reindexObsLayout(newSchema); } diff --git a/client/src/util/stateManager/viewStackHelpers.ts b/client/src/util/stateManager/viewStackHelpers.js similarity index 71% rename from client/src/util/stateManager/viewStackHelpers.ts rename to client/src/util/stateManager/viewStackHelpers.js index dd5d2d94..c1f3bac8 100644 --- a/client/src/util/stateManager/viewStackHelpers.ts +++ b/client/src/util/stateManager/viewStackHelpers.js @@ -37,10 +37,7 @@ Views can be interogated for their type with the following: import { clip, isubsetMask, isubset } from "../../annoMatrix"; import { memoize } from "../dataframe/util"; -import { Dataframe, LabelIndex } from "../dataframe"; -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. export function _clipAnnoMatrix(annoMatrix, min, max) { /* clip the annoMatrix. @@ -50,8 +47,6 @@ export function _clipAnnoMatrix(annoMatrix, min, max) { : clip(annoMatrix, min, max); } -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. export function _userSubsetAnnoMatrix(annoMatrix, mask) { /* user-requested row subset of annoMatrix, to be added on top of any @@ -66,15 +61,12 @@ export function _userSubsetAnnoMatrix(annoMatrix, mask) { annoMatrix.userFlags.isUserSubsetView = true; if (clipRange) { - // @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more. annoMatrix = clip(annoMatrix, ...clipRange); } return annoMatrix; } -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. export function _userResetSubsetAnnoMatrix(annoMatrix) { /* Reset/remove all user-requested subsets. Do not remove clip or embedding subset. @@ -93,16 +85,13 @@ export function _userResetSubsetAnnoMatrix(annoMatrix) { /* re-apply the clip, if any */ if (clipRange) { - // @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more. annoMatrix = clip(annoMatrix, ...clipRange); } return annoMatrix; } -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export function _setEmbeddingSubset(annoMatrix, embeddingDf: Dataframe) { +export function _setEmbeddingSubset(annoMatrix, embeddingDf) { /* Set the embedding subset view. Only create a subset view for the embedding when it is needed, ie, there are NaN values in the embeddings. @@ -135,17 +124,13 @@ export function _setEmbeddingSubset(annoMatrix, embeddingDf: Dataframe) { /* re-apply clip, if needed */ if (clipRange) { - // @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more. annoMatrix = clip(annoMatrix, ...clipRange); } return annoMatrix; } -function _getEmbeddingRowOffsets( - _baseRowIndex: LabelIndex, - embeddingDf: Dataframe -) { +function _getEmbeddingRowOffsets(baseRowIndex, embeddingDf) { /* given a dataframe containing an embedding: - if the embedding contains no NaN coordinates, return null @@ -170,20 +155,16 @@ function _getEmbeddingRowOffsets( return offsets.subarray(0, numOffsets); } -export function _getDiscreteCellEmbeddingRowIndex( - embeddingDf: Dataframe -): LabelIndex { +export function _getDiscreteCellEmbeddingRowIndex(embeddingDf) { const idx = _getEmbeddingRowOffsets(embeddingDf.rowIndex, embeddingDf); if (idx === null) return embeddingDf.rowIndex; return embeddingDf.rowIndex.isubset(idx); } export const getDiscreteCellEmbeddingRowIndex = memoize( _getDiscreteCellEmbeddingRowIndex, - (df: Dataframe) => df.__id + (df) => df.__id ); -// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. export function getEmbSubsetView(annoMatrix) { /* if there is an embedding subset in the view stack, return it. Falsish if not. */ while (annoMatrix.isView) { diff --git a/client/src/util/statemachine/index.ts b/client/src/util/statemachine/index.js similarity index 54% rename from client/src/util/statemachine/index.ts rename to client/src/util/statemachine/index.js index 881bcfc6..3c3f11e0 100644 --- a/client/src/util/statemachine/index.ts +++ b/client/src/util/statemachine/index.js @@ -13,17 +13,18 @@ Where: to: state_name_transitioning_to, from: state_name_transitioning_from, event: value_that_will_cause_transition, - action: callback_upon_transition + action: optional_callback_upon_transition } The transition will be provided to the action callback, so other data may be stored in the transition object for use by the action callback. * onErrorCallback - a callback function called if the FSM receives an event for which it has no defined transition. + Interface: - * states - property containing the state names. A Set(), containing the + * states - property containing the state names. A Set(), contianing the union of to: and from: values. - * events - property containing all of the accepted event values. Set(). + * events - property containing all of the accepted event values. Set(). * graph - a Map of Maps, organized as graph[eventValue][fromStateValue] * clone() - clone the entire statemachine. * next(eventValue) - drive the FSM to the next state. If the event @@ -39,65 +40,24 @@ Example: const fsm = new StateMachine("A", transitions, () => { throw new Error("oops") }); fsm.next("yo"); // returns 42 + */ - -export type FsmState = number | string; -export type FsmEvent = string; // by convention, we assume Events are redux action types, aka strings - -export type FsmActionFn = ( - fsm: StateMachine, - transition: FsmTransition, - data: unknown -) => ActionReturnType; - -export interface FsmTransition { - from: FsmState; - to: FsmState; - event: FsmEvent; - action: FsmActionFn; -} - -export type FsmErrorFn = ( - fsm: StateMachine, - event: FsmEvent, - state: FsmState -) => ActionReturnType; - -export class StateMachine { - events: Set; - - graph: Map>>; - - onError: FsmErrorFn; - - state: FsmState; - - states: Set; - - constructor( - initState: FsmState, - transitions: FsmTransition[], - onError: FsmErrorFn - ) { - this.onError = onError; +export default class StateMachine { + constructor(initState, transitions, onError) { + this.onError = onError || (() => undefined); this.state = initState; // all states this.states = new Set( - transitions.reduce( - (names: Array, tsn: FsmTransition) => { - names.push(tsn.from); - names.push(tsn.to); - return names; - }, - [] - ) + transitions.reduce((names, tsn) => { + names.push(tsn.from); + names.push(tsn.to); + return names; + }, []) ); // all transition names (aka events) - this.events = new Set( - transitions.map((tsn: FsmTransition) => tsn.event) - ); + this.events = new Set(transitions.map((tsn) => tsn.event)); // the transition graph. // graph[event][from] -> transition @@ -110,23 +70,26 @@ export class StateMachine { }, new Map()); } - clone(initState: FsmState): StateMachine { - const fsm = new StateMachine(initState, [], this.onError); + clone(initState) { + const fsm = new StateMachine(initState, []); + fsm.onError = this.onError; fsm.states = this.states; fsm.events = this.events; fsm.graph = this.graph; return fsm; } - next(event: FsmEvent, data: unknown): ActionReturnType { + next(event, data) { const { graph, state } = this; const tsnMap = graph.get(event); - if (!tsnMap) return this.onError(this, event, state); + if (!tsnMap) return this.onError(this, event, state, undefined); const transition = tsnMap.get(state); - if (!transition) return this.onError(this, event, state); + if (!transition) return this.onError(this, event, state, undefined); this.state = transition.to; - return transition.action(this, transition, data); + return transition.action + ? transition.action(this, transition, data) + : undefined; } } diff --git a/client/src/util/typeHelpers.js b/client/src/util/typeHelpers.js new file mode 100644 index 00000000..67858c4f --- /dev/null +++ b/client/src/util/typeHelpers.js @@ -0,0 +1,29 @@ +/* +Various type and schema related helper functions. +*/ + +/* +Utility function to test for a typed array +*/ +export function isTypedArray(x) { + return ( + ArrayBuffer.isView(x) && + Object.prototype.toString.call(x) !== "[object DataView]" + ); +} + +/* +Test for float typed array, ie, Float32TypedArray or Float64TypedArray +*/ +export function isFpTypedArray(x) { + let constructor; + const isFloatArray = + x && + ({ constructor } = x) && + (constructor === Float32Array || constructor === Float64Array); + return isFloatArray; +} + +export function isArrayOrTypedArray(x) { + return Array.isArray(x) || isTypedArray(x); +} diff --git a/client/src/util/typedCrossfilter/bitArray.ts b/client/src/util/typedCrossfilter/bitArray.js similarity index 66% rename from client/src/util/typedCrossfilter/bitArray.ts rename to client/src/util/typedCrossfilter/bitArray.js index 5ee893db..73f7aa78 100644 --- a/client/src/util/typedCrossfilter/bitArray.ts +++ b/client/src/util/typedCrossfilter/bitArray.js @@ -17,23 +17,7 @@ // The underlying data structure uses TypedArrays for performance. // class BitArray { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - bitarray: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - bitmask: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dimensionCount: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - length: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - width: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(length: any) { + constructor(length) { // Initially allocate a 32 bit wide array. allocDimension() will expand // as necessary. // @@ -56,14 +40,12 @@ class BitArray { // Return the number of records that are selected, ie, have a one bit in // all allocated dimensions. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. selectionCount() { return this.countAllOnes(); } // Count all records that have a 'one' bit in allocated dimensions. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. countAllOnes() { let count = 0; const { bitarray, length, width } = this; @@ -94,8 +76,7 @@ class BitArray { // count trailing zeros - hard to do fast in JS! // https://en.wikipedia.org/wiki/Find_first_set#CTZ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static ctz(av: any) { + static ctz(av) { let c = 32; let v = av; v &= -v; // isolate lowest non-zero bit @@ -109,7 +90,6 @@ class BitArray { } // find a free dimension. Return undefined if none - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _findFreeDimension() { let dim; for (let col = 0; col < this.width; col += 1) { @@ -125,7 +105,6 @@ class BitArray { // allocate and return the dimension ID (bit position) // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. allocDimension() { let dim = this._findFreeDimension(); @@ -151,8 +130,7 @@ class BitArray { // free a dimension for later use. MUST deselect the dimension, as other // code assume the column will be zero valued. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - freeDimension(dim: any) { + freeDimension(dim) { // all selection tests assume unallocated dimensions are zero valued. this.deselectAll(dim); const col = dim >>> 5; @@ -162,8 +140,7 @@ class BitArray { // return true if this index is selected in ALL dimensions. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isSelected(index: any) { + isSelected(index) { const { width, length, bitarray } = this; for (let w = 0; w < width; w += 1) { @@ -175,8 +152,7 @@ class BitArray { // return true if this index is selected in ALL dimensions IGNORING dim // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isSelectedIgnoringDim(index: any, dim: any) { + isSelectedIgnoringDim(index, dim) { const ignoreOffset = dim >>> 5; const ignoreMask = ~(1 << dim % 32); @@ -200,8 +176,7 @@ class BitArray { // select index on dimension // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectOne(dim: any, index: any) { + selectOne(dim, index) { const col = dim >>> 5; const before = this.bitarray[col * this.length + index]; const after = before | (1 << dim % 32); @@ -210,8 +185,7 @@ class BitArray { // deselect index on dimension // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - deselectOne(dim: any, index: any) { + deselectOne(dim, index) { const col = dim >>> 5; const before = this.bitarray[col * this.length + index]; const after = before & ~(1 << dim % 32); @@ -220,8 +194,7 @@ class BitArray { // select all indices on dimension. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectAll(dim: any) { + selectAll(dim) { const col = dim >> 5; const one = 1 << dim % 32; for (let i = col * this.length, len = i + this.length; i < len; i += 1) { @@ -231,8 +204,7 @@ class BitArray { // deselect all indices on dimension // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - deselectAll(dim: any) { + deselectAll(dim) { const col = dim >> 5; const zero = ~(1 << dim % 32); for (let i = col * this.length, len = i + this.length; i < len; i += 1) { @@ -242,8 +214,7 @@ class BitArray { // select range of indices on a dimension // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectFromRange(dim: any, range: any) { + selectFromRange(dim, range) { const col = dim >>> 5; const first = range[0]; const last = range[1]; @@ -257,8 +228,7 @@ class BitArray { // select range of indices on a dimension, indirect through a sort map. // Indirect functions are used to map between sort and natural order. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectIndirectFromRange(dim: any, indirect: any, range: any) { + selectIndirectFromRange(dim, indirect, range) { const col = dim >>> 5; const first = range[0]; const last = range[1]; @@ -271,8 +241,7 @@ class BitArray { // deselect range of indices on a dimension // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - deselectFromRange(dim: any, range: any) { + deselectFromRange(dim, range) { const col = dim >>> 5; const first = range[0]; const last = range[1]; @@ -285,8 +254,7 @@ class BitArray { // deselect range of indices on a dimension, indirect through a sort map. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - deselectIndirectFromRange(dim: any, indirect: any, range: any) { + deselectIndirectFromRange(dim, indirect, range) { const col = dim >>> 5; const first = range[0]; const last = range[1]; @@ -300,8 +268,7 @@ class BitArray { // Fill the array with selected|deselected value based upon the // current selection state. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fillBySelection(result: any, selectedValue: any, deselectedValue: any) { + fillBySelection(result, selectedValue, deselectedValue) { // special case (width === 1) for performance if (this.width === 1) { const { bitmask, bitarray } = this; diff --git a/client/src/util/typedCrossfilter/crossfilter.ts b/client/src/util/typedCrossfilter/crossfilter.js similarity index 63% rename from client/src/util/typedCrossfilter/crossfilter.ts rename to client/src/util/typedCrossfilter/crossfilter.js index bc3e5245..6e51d331 100644 --- a/client/src/util/typedCrossfilter/crossfilter.ts +++ b/client/src/util/typedCrossfilter/crossfilter.js @@ -9,11 +9,10 @@ import { upperBoundIndirect, } from "./sort"; import { makeSortIndex } from "./util"; -import { isAnyArray } from "../../common/types/arraytypes"; class NotImplementedError extends Error { - constructor(msg: string) { - super(msg); + constructor(...params) { + super(...params); // Maintains proper stack trace for where our error was thrown (only available on V8) if (Error.captureStackTrace) { @@ -23,17 +22,7 @@ class NotImplementedError extends Error { } export default class ImmutableTypedCrossfilter { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - data: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dimensions: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - selectionCache: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(data: any, dimensions = {}, selectionCache = {}) { + constructor(data, dimensions = {}, selectionCache = {}) { /* Typically, parameter 'data' is one of: - Array of objects/records @@ -62,36 +51,31 @@ export default class ImmutableTypedCrossfilter { Object.preventExtensions(this); } - size(): number { + size() { return this.data.length; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. all() { return this.data; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - setData(data: any) { + setData(data) { if (this.data === data) return this; // please leave, WIP // console.log("...crossfilter set data, will drop cache"); return new ImmutableTypedCrossfilter(data, this.dimensions); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. dimensionNames() { /* return array of all dimensions (by name) */ return Object.keys(this.dimensions); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - hasDimension(name: any) { + hasDimension(name) { return !!this.dimensions[name]; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - addDimension(name: any, type: any, ...rest: any[]) { + addDimension(name, type, ...rest) { /* Add a new dimension to this crossfilter, of type DimensionType. Remainder of parameters are dimension-type-specific. @@ -110,7 +94,6 @@ export default class ImmutableTypedCrossfilter { id = bitArray.allocDimension(); bitArray.selectAll(id); } - // @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 DimensionType = DimTypes[type]; const dim = new DimensionType(name, data, ...rest); Object.freeze(dim); @@ -129,8 +112,7 @@ export default class ImmutableTypedCrossfilter { }); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - delDimension(name: any) { + delDimension(name) { const { data } = this; const { bitArray } = this.selectionCache; const dimensions = { ...this.dimensions }; @@ -150,8 +132,7 @@ export default class ImmutableTypedCrossfilter { }); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - renameDimension(oldName: any, newName: any) { + renameDimension(oldName, newName) { const { [oldName]: dim, ...dimensions } = this.dimensions; const { data, selectionCache } = this; const newDimensions = { @@ -165,8 +146,7 @@ export default class ImmutableTypedCrossfilter { return new ImmutableTypedCrossfilter(data, newDimensions, selectionCache); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - select(name: any, spec: any) { + select(name, spec) { /* select on named dimension, as indicated by `spec`. Spec is an object specifying the selection, and must contain at least a `mode` field. @@ -194,17 +174,7 @@ export default class ImmutableTypedCrossfilter { return new ImmutableTypedCrossfilter(data, dimensions, newSelectionCache); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. - static _dimSelnHasUpdated( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectionCache: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - id: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - newSeln: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - oldSeln: any - ) { + static _dimSelnHasUpdated(selectionCache, id, newSeln, oldSeln) { /* Selection has updated from oldSeln to newSeln. Update the bit array if it exists. If not, we will lazy create it when @@ -238,29 +208,24 @@ export default class ImmutableTypedCrossfilter { If sort index exists in the dimension, assume sort ordered ranges. */ if (oldSeln.index) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dels.forEach((interval: any) => + dels.forEach((interval) => bitArray.deselectIndirectFromRange(id, oldSeln.index, interval) ); } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - dels.forEach((interval: any) => bitArray.deselectFromRange(id, interval)); + dels.forEach((interval) => bitArray.deselectFromRange(id, interval)); } if (newSeln.index) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - adds.forEach((interval: any) => + adds.forEach((interval) => bitArray.selectIndirectFromRange(id, newSeln.index, interval) ); } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - adds.forEach((interval: any) => bitArray.selectFromRange(id, interval)); + adds.forEach((interval) => bitArray.selectFromRange(id, interval)); } return { bitArray }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _getSelectionCache() { if (!this.selectionCache) this.selectionCache = {}; @@ -272,8 +237,7 @@ export default class ImmutableTypedCrossfilter { const id = bitArray.allocDimension(); this.dimensions[name].id = id; const { ranges, index } = selection; - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - ranges.forEach((range: any) => { + ranges.forEach((range) => { if (index) { bitArray.selectIndirectFromRange(id, index, range); } else { @@ -286,19 +250,16 @@ export default class ImmutableTypedCrossfilter { return this.selectionCache; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _clearSelectionCache() { this.selectionCache = {}; return this.selectionCache; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _setSelectionCache(vals = {}) { Object.assign(this.selectionCache, vals); return this.selectionCache; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. allSelected() { /* return array of all records currently selected by all dimensions @@ -319,7 +280,6 @@ export default class ImmutableTypedCrossfilter { return data.isubsetMask(this.allSelectedMask()); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. allSelectedMask() { /* return Uint8Array containing selection state (truthy/falsey) for each record. @@ -338,7 +298,6 @@ export default class ImmutableTypedCrossfilter { return allSelectedMask; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. countSelected() { /* return number of records selected on all dimensions @@ -353,8 +312,7 @@ export default class ImmutableTypedCrossfilter { return countSelected; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - isElementSelected(i: any) { + isElementSelected(i) { /* return truthy/falsey if this record is selected on all dimensions */ @@ -362,8 +320,7 @@ export default class ImmutableTypedCrossfilter { return selectionCache.bitArray.isSelected(i); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - fillByIsSelected(array: any, selectedValue: any, deselectedValue: any) { + fillByIsSelected(array, selectedValue, deselectedValue) { /* fill array with one of two values, based upon selection state. */ @@ -388,11 +345,7 @@ for a dimension: - name - the dimension name/label. */ class _ImmutableBaseDimension { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - name: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - constructor(name: any) { + constructor(name) { this.name = name; } @@ -400,15 +353,13 @@ class _ImmutableBaseDimension { return Object.assign(Object.create(Object.getPrototypeOf(this)), this); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - rename(name: any) { + rename(name) { const d = this.clone(); d.name = name; return d; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - select(spec: any) { + select(spec) { const { mode } = spec; if (mode === undefined) { throw new Error("select spec does not contain 'mode'"); @@ -420,14 +371,7 @@ class _ImmutableBaseDimension { } class ImmutableScalarDimension extends _ImmutableBaseDimension { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - index: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(name: any, data: any, value: any, ValueArrayType: any) { + constructor(name, data, value, ValueArrayType) { super(name); // Three modes - caller can provide a pre-created value array, @@ -449,13 +393,12 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { value, new ValueArrayType(data.length) ); - } else if (isAnyArray(value)) { + } else if (isArrayOrTypedArray(value)) { // Create value array from user-provided array. Typically used // only by enumerated dimensions array = this._createValueArray( data, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - (i: any) => value[i], + (i) => value[i], new ValueArrayType(data.length) ); } else { @@ -469,8 +412,8 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { this.index = makeSortIndex(array); } - // eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- needed for polymorphism - _createValueArray(data: any, mapf: any, array: any) { + // eslint-disable-next-line class-methods-use-this -- needed for polymorphism + _createValueArray(data, mapf, array) { // create dimension value array const len = data.length; const larray = array; @@ -480,8 +423,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { return larray; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - select(spec: any) { + select(spec) { const { mode } = spec; const { index } = this; switch (mode) { @@ -498,8 +440,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectExact(spec: any) { + selectExact(spec) { const { value, index } = this; let { values } = spec; if (!Array.isArray(values)) { @@ -518,8 +459,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { return { ranges, index }; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectRange(spec: any) { + selectRange(spec) { const { value, index } = this; /* if !inclusive: [lo, hi) else [lo, hi] @@ -538,13 +478,11 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension { } class ImmutableEnumDimension extends ImmutableScalarDimension { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(name: any, data: any, value: any) { + constructor(name, data, value) { super(name, data, value, Uint32Array); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - _createValueArray(data: any, mapf: any, array: any) { + _createValueArray(data, mapf, array) { const len = data.length; const larray = array; @@ -555,7 +493,6 @@ class ImmutableEnumDimension extends ImmutableScalarDimension { s.add(mapf(i, data)); } const enumIndex = sortArray(Array.from(s)); - // @ts-expect-error FIXME Adding enumIndex as member variable results in "undefined" enumIndex value this.enumIndex = enumIndex; // create dimension value array @@ -568,9 +505,7 @@ class ImmutableEnumDimension extends ImmutableScalarDimension { return larray; } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectExact(spec: any) { - // @ts-expect-error FIXME Adding enumIndex as member variable results in "undefined" enumIndex value + selectExact(spec) { const { enumIndex } = this; let { values } = spec; if (!Array.isArray(values)) { @@ -578,35 +513,20 @@ class ImmutableEnumDimension extends ImmutableScalarDimension { } return super.selectExact({ mode: spec.mode, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - values: values.map((v: any) => + values: values.map((v) => binarySearch(enumIndex, v, 0, enumIndex.length) ), }); } - // @ts-expect-error ts-migrate(2416) FIXME: Property 'selectRange' in type 'ImmutableEnumDimen... Remove this comment to see the full error message - // eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types -- enables polymorphism + // eslint-disable-next-line class-methods-use-this -- enables polymorphism selectRange() { throw new Error("range selection unsupported on Enumerated dimension"); } } class ImmutableSpatialDimension extends _ImmutableBaseDimension { - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - X: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - Xindex: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - Y: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - Yindex: any; - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - constructor(name: any, data: any, X: any, Y: any) { + constructor(name, data, X, Y) { super(name); if (X.length !== Y.length && X.length !== data.length) { @@ -621,8 +541,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension { this.Yindex = makeSortIndex(Y); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - select(spec: any) { + select(spec) { const { mode } = spec; switch (mode) { case "all": @@ -638,8 +557,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension { } } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectWithinRect(spec: any) { + selectWithinRect(spec) { /* { mode: "within-rect", minX: 1, minY: 0, maxX: 3, maxY: 9 } */ @@ -672,8 +590,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension { * then the polygon test is applied */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - selectWithinPolygon(spec: any) { + selectWithinPolygon(spec) { /* { mode: "within-polygon", polygon: [ [x0, y0], ... ] } */ @@ -728,9 +645,16 @@ export const DimTypes = { spatial: ImmutableSpatialDimension, }; +function isArrayOrTypedArray(x) { + return ( + Array.isArray(x) || + (ArrayBuffer.isView(x) && + Object.prototype.toString.call(x) !== "[object DataView]") + ); +} + /* return bounding box of the polygon */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function polygonBoundingBox(polygon: any) { +function polygonBoundingBox(polygon) { let minX = Number.MAX_VALUE; let minY = Number.MAX_VALUE; let maxX = Number.MIN_VALUE; @@ -754,8 +678,7 @@ function polygonBoundingBox(polygon: any) { * @param {float} y - point y coordinate * @type {boolean} */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function withinPolygon(polygon: any, x: any, y: any) { +function withinPolygon(polygon, x, y) { const n = polygon.length; let p = polygon[n - 1]; let x0 = p[0]; diff --git a/client/src/util/typedCrossfilter/index.ts b/client/src/util/typedCrossfilter/index.js similarity index 100% rename from client/src/util/typedCrossfilter/index.ts rename to client/src/util/typedCrossfilter/index.js diff --git a/client/src/util/typedCrossfilter/positiveIntervals.ts b/client/src/util/typedCrossfilter/positiveIntervals.js similarity index 75% rename from client/src/util/typedCrossfilter/positiveIntervals.ts rename to client/src/util/typedCrossfilter/positiveIntervals.js index 2545fd4c..8fe7e54f 100644 --- a/client/src/util/typedCrossfilter/positiveIntervals.ts +++ b/client/src/util/typedCrossfilter/positiveIntervals.js @@ -16,12 +16,10 @@ class PositiveIntervals { // 1. no overlapping intervals // 2. sorted in order of interval min. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static canonicalize(A: any) { + static canonicalize(A) { if (A.length <= 1) return A; const copy = A.slice(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - copy.sort((a: any, b: any) => a[0] - b[0]); + copy.sort((a, b) => a[0] - b[0]); const res = []; res.push(copy[0]); for (let i = 1, len = copy.length; i < len; i += 1) { @@ -40,13 +38,11 @@ class PositiveIntervals { // Return interval with values belonging to both A and B. Essentially // a set union operation. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static union(A: any, B: any) { + static union(A, B) { return PositiveIntervals.canonicalize([...A, ...B]); } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static _flatten(A: any, B: any) { + static _flatten(A, B) { const points = []; /* point, A, start */ for (let a = 0; a < A.length; a += 1) { points.push([A[a][0], true, true]); @@ -64,8 +60,7 @@ class PositiveIntervals { // A - B, ie, the interval with all values in A that are not in B. Essentially // a set difference operation. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static difference(A: any, B: any) { + static difference(A, B) { // Corner cases if (A.length === 0 || B.length === 0) { return PositiveIntervals.canonicalize(A); @@ -101,8 +96,7 @@ class PositiveIntervals { // Return interval with values belonging to A or B. Essentially a set // intersection. // - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - static intersection(A: any, B: any) { + static intersection(A, B) { if (A.length === 0 || B.length === 0) { return []; } diff --git a/client/src/util/typedCrossfilter/sort.js b/client/src/util/typedCrossfilter/sort.js new file mode 100644 index 00000000..700d1de4 --- /dev/null +++ b/client/src/util/typedCrossfilter/sort.js @@ -0,0 +1,429 @@ +import { isTypedArray, isFpTypedArray } from "../typeHelpers"; + +/* eslint-disable no-bitwise -- code relies on bitwise ops */ + +/* + ** fast sort and search, with separate code paths for floats (NaN ordering), + ** indirect and direct search/sort. + */ + +/* +Comparators for float sort. -Infinity < finite < Infinity < NaN +*/ +function lt(a, b) { + if (Number.isNaN(b)) return !Number.isNaN(a); + return a < b; +} + +function gt(a, b) { + if (Number.isNaN(a)) return !Number.isNaN(b); + return a > b; +} + +/* +insertion sort, used for small arrays (controlled by SMALL_ARRAY constant) +*/ +const SMALL_ARRAY = 32; +function insertionsort(a, lo, hi) { + for (let i = lo + 1; i < hi + 1; i += 1) { + const x = a[i]; + let j; + for (j = i; j > lo && a[j - 1] > x; j -= 1) { + a[j] = a[j - 1]; + } + a[j] = x; + } + return a; +} + +function insertionsortFloats(a, lo, hi) { + for (let i = lo + 1; i < hi + 1; i += 1) { + const x = a[i]; + let j; + for (j = i; j > lo && gt(a[j - 1], x); j -= 1) { + a[j] = a[j - 1]; + } + a[j] = x; + } + return a; +} + +function insertionsortIndirect(a, s, lo, hi) { + for (let i = lo + 1; i < hi + 1; i += 1) { + const x = a[i]; + const t = s[x]; + let j; + for (j = i; j > lo && s[a[j - 1]] > t; j -= 1) { + a[j] = a[j - 1]; + } + a[j] = x; + } + return a; +} + +function insertionsortFloatsIndirect(a, s, lo, hi) { + for (let i = lo + 1; i < hi + 1; i += 1) { + const x = a[i]; + const t = s[x]; + let j; + for (j = i; j > lo && gt(s[a[j - 1]], t); j -= 1) { + a[j] = a[j - 1]; + } + a[j] = x; + } + return a; +} + +/* +Quicksort - used for larger arrays +*/ +function quicksort(a, lo, hi) { + if (hi - lo < SMALL_ARRAY) { + return insertionsort(a, lo, hi); + } + if (lo < hi) { + // partition + const mid = Math.floor((lo + hi) / 2); + const p = a[mid]; + let i = lo - 1; + let j = hi + 1; + while (i < j) { + do { + i += 1; + } while (a[i] < p); + do { + j -= 1; + } while (a[j] > p); + if (i < j) { + const tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + } + // sort + quicksort(a, lo, j); + quicksort(a, j + 1, hi); + } + return a; +} + +function quicksortFloats(a, lo, hi) { + if (hi - lo < SMALL_ARRAY) { + return insertionsortFloats(a, lo, hi); + } + if (lo < hi) { + // partition + const mid = Math.floor((lo + hi) / 2); + const p = a[mid]; + let i = lo - 1; + let j = hi + 1; + while (i < j) { + do { + i += 1; + } while (lt(a[i], p)); + do { + j -= 1; + } while (gt(a[j], p)); + if (i < j) { + const tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + } + // sort + quicksortFloats(a, lo, j); + quicksortFloats(a, j + 1, hi); + } + return a; +} + +function quicksortIndirect(a, s, lo, hi) { + if (hi - lo < SMALL_ARRAY) { + return insertionsortIndirect(a, s, lo, hi); + } + if (lo < hi) { + // partition + const mid = Math.floor((lo + hi) / 2); + const p = a[mid]; + const t = s[p]; + let i = lo - 1; + let j = hi + 1; + while (i < j) { + do { + i += 1; + } while (s[a[i]] < t); + do { + j -= 1; + } while (s[a[j]] > t); + if (i < j) { + const tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + } + // sort + quicksortIndirect(a, s, lo, j); + quicksortIndirect(a, s, j + 1, hi); + } + return a; +} + +function quicksortFloatsIndirect(a, s, lo, hi) { + if (hi - lo < SMALL_ARRAY) { + return insertionsortFloatsIndirect(a, s, lo, hi); + } + if (lo < hi) { + // partition + const mid = Math.floor((lo + hi) / 2); + const p = a[mid]; + const t = s[p]; + let i = lo - 1; + let j = hi + 1; + while (i < j) { + do { + i += 1; + } while (lt(s[a[i]], t)); + do { + j -= 1; + } while (gt(s[a[j]], t)); + if (i < j) { + const tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + } + // sort + quicksortFloatsIndirect(a, s, lo, j); + quicksortFloatsIndirect(a, s, j + 1, hi); + } + return a; +} + +/* +Convenience wrappers, handling optimization paths and default +handlers for NaN comparisons. Sorts in place. +*/ +export function sortArray(arr) { + if (Array.isArray(arr)) { + return quicksort(arr, 0, arr.length - 1); + } + if (isTypedArray(arr)) { + if (isFpTypedArray(arr)) { + return quicksortFloats(arr, 0, arr.length - 1); + } + return quicksort(arr, 0, arr.length - 1); + } + /* else unsupported */ + throw new Error("sortArray received unsupported object type"); +} + +export function sortIndex(index, source) { + if (isFpTypedArray(source)) + return quicksortFloatsIndirect(index, source, 0, index.length - 1); + return quicksortIndirect(index, source, 0, index.length - 1); +} + +// Search for `value` in the sorted array `arr`, in the range [first, last). +// Return the first (left most) index where arr[index] >= value. +// +// In other words, return array index I where: +// arr[i] < value for all tarr[lo:I] +// arr[i] >= value for all tarr[I:last] +// +// The same semantics/behavior as: +// C++: lower_bound() +// Python: bisect.bisect_left() +// +function lowerBoundNonFloat(valueArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (valueArray[middle] < value) { + lfirst = middle + 1; + } else { + llast = middle; + } + } + return lfirst; +} + +// lowerBound, but with NaN handling +// +// If the underlying array is a Float32Array or Float64Array, will enforce +// the ordering -Infinity < finite < Infinity < NaN. +// +function lowerBoundFloat(valueArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (lt(valueArray[middle], value)) { + lfirst = middle + 1; + } else { + llast = middle; + } + } + return lfirst; +} + +export function lowerBound(valueArray, value, first, last) { + if (isFpTypedArray(valueArray)) { + return lowerBoundFloat(valueArray, value, first, last); + } + return lowerBoundNonFloat(valueArray, value, first, last); +} + +// Inlined performance optimization - used to indirect through a sort map. +// +function lowerBoundNonFloatIndirect( + valueArray, + indexArray, + value, + first, + last +) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (valueArray[indexArray[middle]] < value) { + lfirst = middle + 1; + } else { + llast = middle; + } + } + return lfirst; +} + +function lowerBoundFloatIndirect(valueArray, indexArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (lt(valueArray[indexArray[middle]], value)) { + lfirst = middle + 1; + } else { + llast = middle; + } + } + return lfirst; +} + +export function lowerBoundIndirect(valueArray, indexArray, value, first, last) { + if (isFpTypedArray(valueArray)) { + return lowerBoundFloatIndirect(valueArray, indexArray, value, first, last); + } + return lowerBoundNonFloatIndirect(valueArray, indexArray, value, first, last); +} + +// Search for `value in the sorted array `arr`, in the range [first, last). +// Return the first value where arr[index] > value. +// +// In other words, return array index I, where: +// arr[i] <= value for all tarr[lo:I] +// arr[i] > value for all tarr[I:last] +// +// The same semantics/behavior as: +// C++: upper_bound() +// Python: bisect.bisect_right() +// +function upperBoundNonFloat(valueArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (valueArray[middle] > value) { + llast = middle; + } else { + lfirst = middle + 1; + } + } + return lfirst; +} + +function upperBoundFloat(valueArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (gt(valueArray[middle], value)) { + llast = middle; + } else { + lfirst = middle + 1; + } + } + return lfirst; +} + +export function upperBound(valueArray, value, first, last) { + if (isFpTypedArray(valueArray)) { + return upperBoundFloat(valueArray, value, first, last); + } + return upperBoundNonFloat(valueArray, value, first, last); +} + +// Inline performance optimization +// +function upperBoundNonFloatIndirect( + valueArray, + indexArray, + value, + first, + last +) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (valueArray[indexArray[middle]] > value) { + llast = middle; + } else { + lfirst = middle + 1; + } + } + return lfirst; +} + +function upperBoundFloatIndirect(valueArray, indexArray, value, first, last) { + let lfirst = first; + let llast = last; + // this is just a binary search + while (lfirst < llast) { + const middle = (lfirst + llast) >>> 1; + if (gt(valueArray[indexArray[middle]], value)) { + llast = middle; + } else { + lfirst = middle + 1; + } + } + return lfirst; +} + +export function upperBoundIndirect(valueArray, indexArray, value, first, last) { + if (isFpTypedArray(valueArray)) { + return upperBoundFloatIndirect(valueArray, indexArray, value, first, last); + } + return upperBoundNonFloatIndirect(valueArray, indexArray, value, first, last); +} + +// Search for `value` in the sorted array `arr`, in the range [first, last). +// Return the first index where arr[index] == value, OR if value not present, +// return `last` +// +// The same semantics/behavior as: +// C++: binary_search() +// +export function binarySearch(valueArray, value, first, last) { + const index = lowerBound(valueArray, value, first, last); + if (index !== last && value === valueArray[index]) return index; + return last; +} +/* eslint-enable no-bitwise -- enable */ diff --git a/client/src/util/typedCrossfilter/sort.ts b/client/src/util/typedCrossfilter/sort.ts deleted file mode 100644 index 8a41f989..00000000 --- a/client/src/util/typedCrossfilter/sort.ts +++ /dev/null @@ -1,529 +0,0 @@ -import { isTypedArray, isFloatTypedArray } from "../../common/types/arraytypes"; - -/* eslint-disable no-bitwise -- code relies on bitwise ops */ - -/* - ** fast sort and search, with separate code paths for floats (NaN ordering), - ** indirect and direct search/sort. - */ - -/* -Comparators for float sort. -Infinity < finite < Infinity < NaN -*/ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function lt(a: any, b: any) { - if (Number.isNaN(b)) return !Number.isNaN(a); - return a < b; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function gt(a: any, b: any) { - if (Number.isNaN(a)) return !Number.isNaN(b); - return a > b; -} - -/* -insertion sort, used for small arrays (controlled by SMALL_ARRAY constant) -*/ -const SMALL_ARRAY = 32; -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function insertionsort(a: any, lo: any, hi: any) { - for (let i = lo + 1; i < hi + 1; i += 1) { - const x = a[i]; - let j; - for (j = i; j > lo && a[j - 1] > x; j -= 1) { - a[j] = a[j - 1]; - } - a[j] = x; - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function insertionsortFloats(a: any, lo: any, hi: any) { - for (let i = lo + 1; i < hi + 1; i += 1) { - const x = a[i]; - let j; - for (j = i; j > lo && gt(a[j - 1], x); j -= 1) { - a[j] = a[j - 1]; - } - a[j] = x; - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function insertionsortIndirect(a: any, s: any, lo: any, hi: any) { - for (let i = lo + 1; i < hi + 1; i += 1) { - const x = a[i]; - const t = s[x]; - let j; - for (j = i; j > lo && s[a[j - 1]] > t; j -= 1) { - a[j] = a[j - 1]; - } - a[j] = x; - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function insertionsortFloatsIndirect(a: any, s: any, lo: any, hi: any) { - for (let i = lo + 1; i < hi + 1; i += 1) { - const x = a[i]; - const t = s[x]; - let j; - for (j = i; j > lo && gt(s[a[j - 1]], t); j -= 1) { - a[j] = a[j - 1]; - } - a[j] = x; - } - return a; -} - -/* -Quicksort - used for larger arrays -*/ -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function quicksort(a: any, lo: any, hi: any) { - if (hi - lo < SMALL_ARRAY) { - return insertionsort(a, lo, hi); - } - if (lo < hi) { - // partition - const mid = Math.floor((lo + hi) / 2); - const p = a[mid]; - let i = lo - 1; - let j = hi + 1; - while (i < j) { - do { - i += 1; - } while (a[i] < p); - do { - j -= 1; - } while (a[j] > p); - if (i < j) { - const tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; - } - } - // sort - quicksort(a, lo, j); - quicksort(a, j + 1, hi); - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function quicksortFloats(a: any, lo: any, hi: any) { - if (hi - lo < SMALL_ARRAY) { - return insertionsortFloats(a, lo, hi); - } - if (lo < hi) { - // partition - const mid = Math.floor((lo + hi) / 2); - const p = a[mid]; - let i = lo - 1; - let j = hi + 1; - while (i < j) { - do { - i += 1; - } while (lt(a[i], p)); - do { - j -= 1; - } while (gt(a[j], p)); - if (i < j) { - const tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; - } - } - // sort - quicksortFloats(a, lo, j); - quicksortFloats(a, j + 1, hi); - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function quicksortIndirect(a: any, s: any, lo: any, hi: any) { - if (hi - lo < SMALL_ARRAY) { - return insertionsortIndirect(a, s, lo, hi); - } - if (lo < hi) { - // partition - const mid = Math.floor((lo + hi) / 2); - const p = a[mid]; - const t = s[p]; - let i = lo - 1; - let j = hi + 1; - while (i < j) { - do { - i += 1; - } while (s[a[i]] < t); - do { - j -= 1; - } while (s[a[j]] > t); - if (i < j) { - const tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; - } - } - // sort - quicksortIndirect(a, s, lo, j); - quicksortIndirect(a, s, j + 1, hi); - } - return a; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function quicksortFloatsIndirect(a: any, s: any, lo: any, hi: any) { - if (hi - lo < SMALL_ARRAY) { - return insertionsortFloatsIndirect(a, s, lo, hi); - } - if (lo < hi) { - // partition - const mid = Math.floor((lo + hi) / 2); - const p = a[mid]; - const t = s[p]; - let i = lo - 1; - let j = hi + 1; - while (i < j) { - do { - i += 1; - } while (lt(s[a[i]], t)); - do { - j -= 1; - } while (gt(s[a[j]], t)); - if (i < j) { - const tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; - } - } - // sort - quicksortFloatsIndirect(a, s, lo, j); - quicksortFloatsIndirect(a, s, j + 1, hi); - } - return a; -} - -/* -Convenience wrappers, handling optimization paths and default -handlers for NaN comparisons. Sorts in place. -*/ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function sortArray(arr: any) { - if (Array.isArray(arr)) { - return quicksort(arr, 0, arr.length - 1); - } - if (isTypedArray(arr)) { - if (isFloatTypedArray(arr)) { - return quicksortFloats(arr, 0, arr.length - 1); - } - return quicksort(arr, 0, arr.length - 1); - } - /* else unsupported */ - throw new Error("sortArray received unsupported object type"); -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function sortIndex(index: any, source: any) { - if (isFloatTypedArray(source)) - return quicksortFloatsIndirect(index, source, 0, index.length - 1); - return quicksortIndirect(index, source, 0, index.length - 1); -} - -// Search for `value` in the sorted array `arr`, in the range [first, last). -// Return the first (left most) index where arr[index] >= value. -// -// In other words, return array index I where: -// arr[i] < value for all tarr[lo:I] -// arr[i] >= value for all tarr[I:last] -// -// The same semantics/behavior as: -// C++: lower_bound() -// Python: bisect.bisect_left() -// -function lowerBoundNonFloat( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (valueArray[middle] < value) { - lfirst = middle + 1; - } else { - llast = middle; - } - } - return lfirst; -} - -// lowerBound, but with NaN handling -// -// If the underlying array is a Float32Array or Float64Array, will enforce -// the ordering -Infinity < finite < Infinity < NaN. -// -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function lowerBoundFloat(valueArray: any, value: any, first: any, last: any) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (lt(valueArray[middle], value)) { - lfirst = middle + 1; - } else { - llast = middle; - } - } - return lfirst; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function lowerBound(valueArray: any, value: any, first: any, last: any) { - if (isFloatTypedArray(valueArray)) { - return lowerBoundFloat(valueArray, value, first, last); - } - return lowerBoundNonFloat(valueArray, value, first, last); -} - -// Inlined performance optimization - used to indirect through a sort map. -// -function lowerBoundNonFloatIndirect( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (valueArray[indexArray[middle]] < value) { - lfirst = middle + 1; - } else { - llast = middle; - } - } - return lfirst; -} - -function lowerBoundFloatIndirect( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (lt(valueArray[indexArray[middle]], value)) { - lfirst = middle + 1; - } else { - llast = middle; - } - } - return lfirst; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export function lowerBoundIndirect( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - last: any -) { - if (isFloatTypedArray(valueArray)) { - return lowerBoundFloatIndirect(valueArray, indexArray, value, first, last); - } - return lowerBoundNonFloatIndirect(valueArray, indexArray, value, first, last); -} - -// Search for `value in the sorted array `arr`, in the range [first, last). -// Return the first value where arr[index] > value. -// -// In other words, return array index I, where: -// arr[i] <= value for all tarr[lo:I] -// arr[i] > value for all tarr[I:last] -// -// The same semantics/behavior as: -// C++: upper_bound() -// Python: bisect.bisect_right() -// -function upperBoundNonFloat( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (valueArray[middle] > value) { - llast = middle; - } else { - lfirst = middle + 1; - } - } - return lfirst; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. -function upperBoundFloat(valueArray: any, value: any, first: any, last: any) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (gt(valueArray[middle], value)) { - llast = middle; - } else { - lfirst = middle + 1; - } - } - return lfirst; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function upperBound(valueArray: any, value: any, first: any, last: any) { - if (isFloatTypedArray(valueArray)) { - return upperBoundFloat(valueArray, value, first, last); - } - return upperBoundNonFloat(valueArray, value, first, last); -} - -// Inline performance optimization -// -function upperBoundNonFloatIndirect( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (valueArray[indexArray[middle]] > value) { - llast = middle; - } else { - lfirst = middle + 1; - } - } - return lfirst; -} - -function upperBoundFloatIndirect( - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. - last: any -) { - let lfirst = first; - let llast = last; - // this is just a binary search - while (lfirst < llast) { - const middle = (lfirst + llast) >>> 1; - if (gt(valueArray[indexArray[middle]], value)) { - llast = middle; - } else { - lfirst = middle + 1; - } - } - return lfirst; -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export function upperBoundIndirect( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - indexArray: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - last: any -) { - if (isFloatTypedArray(valueArray)) { - return upperBoundFloatIndirect(valueArray, indexArray, value, first, last); - } - return upperBoundNonFloatIndirect(valueArray, indexArray, value, first, last); -} - -// Search for `value` in the sorted array `arr`, in the range [first, last). -// Return the first index where arr[index] == value, OR if value not present, -// return `last` -// -// The same semantics/behavior as: -// C++: binary_search() -// -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. -export function binarySearch( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - valueArray: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - value: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - first: any, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. - last: any -) { - const index = lowerBound(valueArray, value, first, last); - if (index !== last && value === valueArray[index]) return index; - return last; -} -/* eslint-enable no-bitwise -- enable */ diff --git a/client/src/util/typedCrossfilter/util.ts b/client/src/util/typedCrossfilter/util.js similarity index 54% rename from client/src/util/typedCrossfilter/util.ts rename to client/src/util/typedCrossfilter/util.js index a56f954f..8d28d65a 100644 --- a/client/src/util/typedCrossfilter/util.ts +++ b/client/src/util/typedCrossfilter/util.js @@ -7,8 +7,7 @@ import { rangeFill as fillRange } from "../range"; // slice out of one array into another, using an index array // -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function sliceByIndex(src: any, index: any) { +export function sliceByIndex(src, index) { if (index === undefined || index === null) { return src; } @@ -19,8 +18,7 @@ export function sliceByIndex(src: any, index: any) { return dst; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. -export function makeSortIndex(src: any) { +export function makeSortIndex(src) { const index = fillRange(new Uint32Array(src.length)); sortIndex(index, src); return index; diff --git a/client/tsconfig.json b/client/tsconfig.json deleted file mode 100644 index b0559eac..00000000 --- a/client/tsconfig.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "esModuleInterop": true, - // Allow @connect - "experimentalDecorators": true, - // Ensure Babel can safely transpile files - "isolatedModules": true, - "jsx": "preserve", - "lib": ["dom", "es2020"], - "module": "esnext", - "moduleResolution": "node", - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "skipLibCheck": true, - "strict": true, - "target": "esnext", - "types": [ - "jest", - "puppeteer", - "jest-environment-puppeteer", - "expect-puppeteer" - ], - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true - }, - "include": [ - "src/**/*", - "configuration/**/*", - "__tests__/**/*", - "jest-puppeteer.config.js" - ], - "exclude": ["node_modules", "__tests__/e2e/__snapshots__/**/*"] -} diff --git a/dev_docs/e2e_tests.md b/dev_docs/e2e_tests.md index 4c1bd101..c2730fed 100644 --- a/dev_docs/e2e_tests.md +++ b/dev_docs/e2e_tests.md @@ -79,10 +79,10 @@ See [developer guidelines](developer_guidelines.md) ```ts { - "e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.ts", + "e2e": "jest --config __tests__/e2e/e2eJestConfig.json e2e/e2e.test.js", } ``` - which tells `jest` to use `e2eJestConfig.json` as the config file to run e2e test file `e2e.test.ts` + which tells `jest` to use `e2eJestConfig.json` as the config file to run e2e test file `e2e.test.js` 1. [puppeteer.setup.js](../client/__tests__/e2e/puppeteer.setup.js) is for configuring `jest`, `browser`, and `page` objects at runtime