Extract sorting to separate functions
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
|
import { ExternalApiUsage } from "../external-api-usage";
|
||||||
|
|
||||||
export function calculateModeledPercentage(
|
export function calculateModeledPercentage(
|
||||||
externalApiUsages: Array<Pick<ExternalApiUsage, "supported">>,
|
externalApiUsages: Array<Pick<ExternalApiUsage, "supported">>,
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { ExternalApiUsage } from "../external-api-usage";
|
||||||
|
import { Mode } from "./mode";
|
||||||
|
import { calculateModeledPercentage } from "./modeled-percentage";
|
||||||
|
|
||||||
|
export function groupMethods(
|
||||||
|
externalApiUsages: ExternalApiUsage[],
|
||||||
|
mode: Mode,
|
||||||
|
): Record<string, ExternalApiUsage[]> {
|
||||||
|
const groupedByLibrary: Record<string, ExternalApiUsage[]> = {};
|
||||||
|
|
||||||
|
for (const externalApiUsage of externalApiUsages) {
|
||||||
|
// Group by package if using framework mode
|
||||||
|
const key =
|
||||||
|
mode === Mode.Framework
|
||||||
|
? externalApiUsage.packageName
|
||||||
|
: externalApiUsage.library;
|
||||||
|
|
||||||
|
groupedByLibrary[key] ??= [];
|
||||||
|
groupedByLibrary[key].push(externalApiUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupedByLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortGroupNames(
|
||||||
|
methods: Record<string, ExternalApiUsage[]>,
|
||||||
|
): string[] {
|
||||||
|
return Object.keys(methods).sort((a, b) =>
|
||||||
|
compareGroups(methods[a], a, methods[b], b),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortMethods(
|
||||||
|
externalApiUsages: ExternalApiUsage[],
|
||||||
|
): ExternalApiUsage[] {
|
||||||
|
const sortedExternalApiUsages = [...externalApiUsages];
|
||||||
|
sortedExternalApiUsages.sort((a, b) => compareMethod(a, b));
|
||||||
|
return sortedExternalApiUsages;
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareGroups(
|
||||||
|
a: ExternalApiUsage[],
|
||||||
|
aName: string,
|
||||||
|
b: ExternalApiUsage[],
|
||||||
|
bName: string,
|
||||||
|
): number {
|
||||||
|
const supportedPercentageA = calculateModeledPercentage(a);
|
||||||
|
const supportedPercentageB = calculateModeledPercentage(b);
|
||||||
|
|
||||||
|
// Sort first by supported percentage ascending
|
||||||
|
if (supportedPercentageA > supportedPercentageB) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (supportedPercentageA < supportedPercentageB) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberOfUsagesA = a.reduce((acc, curr) => acc + curr.usages.length, 0);
|
||||||
|
const numberOfUsagesB = b.reduce((acc, curr) => acc + curr.usages.length, 0);
|
||||||
|
|
||||||
|
// If the number of usages is equal, sort by number of methods descending
|
||||||
|
if (numberOfUsagesA === numberOfUsagesB) {
|
||||||
|
const numberOfMethodsA = a.length;
|
||||||
|
const numberOfMethodsB = b.length;
|
||||||
|
|
||||||
|
// If the number of methods is equal, sort by library name ascending
|
||||||
|
if (numberOfMethodsA === numberOfMethodsB) {
|
||||||
|
return aName.localeCompare(bName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return numberOfMethodsB - numberOfMethodsA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then sort by number of usages descending
|
||||||
|
return numberOfUsagesB - numberOfUsagesA;
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareMethod(a: ExternalApiUsage, b: ExternalApiUsage): number {
|
||||||
|
// Sort first by supported, putting unmodeled methods first.
|
||||||
|
if (a.supported && !b.supported) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!a.supported && b.supported) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Then sort by number of usages descending
|
||||||
|
return b.usages.length - a.usages.length;
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usag
|
|||||||
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
||||||
import { assertNever } from "../../common/helpers-pure";
|
import { assertNever } from "../../common/helpers-pure";
|
||||||
import { vscode } from "../vscode-api";
|
import { vscode } from "../vscode-api";
|
||||||
import { calculateModeledPercentage } from "./modeled";
|
import { calculateModeledPercentage } from "../../data-extensions-editor/shared/modeled-percentage";
|
||||||
import { LinkIconButton } from "../variant-analysis/LinkIconButton";
|
import { LinkIconButton } from "../variant-analysis/LinkIconButton";
|
||||||
import { ViewTitle } from "../common";
|
import { ViewTitle } from "../common";
|
||||||
import { DataExtensionEditorViewState } from "../../data-extensions-editor/shared/view-state";
|
import { DataExtensionEditorViewState } from "../../data-extensions-editor/shared/view-state";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usag
|
|||||||
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
||||||
import { pluralize } from "../../common/word";
|
import { pluralize } from "../../common/word";
|
||||||
import { ModeledMethodDataGrid } from "./ModeledMethodDataGrid";
|
import { ModeledMethodDataGrid } from "./ModeledMethodDataGrid";
|
||||||
import { calculateModeledPercentage } from "./modeled";
|
import { calculateModeledPercentage } from "../../data-extensions-editor/shared/modeled-percentage";
|
||||||
import { decimalFormatter, percentFormatter } from "./formatters";
|
import { decimalFormatter, percentFormatter } from "./formatters";
|
||||||
import { Codicon } from "../common";
|
import { Codicon } from "../common";
|
||||||
import { Mode } from "../../data-extensions-editor/shared/mode";
|
import { Mode } from "../../data-extensions-editor/shared/mode";
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usag
|
|||||||
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { Mode } from "../../data-extensions-editor/shared/mode";
|
import { Mode } from "../../data-extensions-editor/shared/mode";
|
||||||
|
import { sortMethods } from "../../data-extensions-editor/shared/sorting";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
externalApiUsages: ExternalApiUsage[];
|
externalApiUsages: ExternalApiUsage[];
|
||||||
@@ -26,21 +27,10 @@ export const ModeledMethodDataGrid = ({
|
|||||||
mode,
|
mode,
|
||||||
onChange,
|
onChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const sortedExternalApiUsages = useMemo(() => {
|
const sortedExternalApiUsages = useMemo(
|
||||||
const sortedExternalApiUsages = [...externalApiUsages];
|
() => sortMethods(externalApiUsages),
|
||||||
sortedExternalApiUsages.sort((a, b) => {
|
[externalApiUsages],
|
||||||
// Sort first by supported, putting unmodeled methods first.
|
);
|
||||||
if (a.supported && !b.supported) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!a.supported && b.supported) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Then sort by number of usages descending
|
|
||||||
return b.usages.length - a.usages.length;
|
|
||||||
});
|
|
||||||
return sortedExternalApiUsages;
|
|
||||||
}, [externalApiUsages]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VSCodeDataGrid>
|
<VSCodeDataGrid>
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ import * as React from "react";
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
|
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
|
||||||
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
|
||||||
import { calculateModeledPercentage } from "./modeled";
|
|
||||||
import { LibraryRow } from "./LibraryRow";
|
import { LibraryRow } from "./LibraryRow";
|
||||||
import { Mode } from "../../data-extensions-editor/shared/mode";
|
import { Mode } from "../../data-extensions-editor/shared/mode";
|
||||||
|
import {
|
||||||
|
groupMethods,
|
||||||
|
sortGroupNames,
|
||||||
|
} from "../../data-extensions-editor/shared/sorting";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
externalApiUsages: ExternalApiUsage[];
|
externalApiUsages: ExternalApiUsage[];
|
||||||
@@ -22,62 +25,12 @@ export const ModeledMethodsList = ({
|
|||||||
mode,
|
mode,
|
||||||
onChange,
|
onChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const grouped = useMemo(() => {
|
const grouped = useMemo(
|
||||||
const groupedByLibrary: Record<string, ExternalApiUsage[]> = {};
|
() => groupMethods(externalApiUsages, mode),
|
||||||
|
[externalApiUsages, mode],
|
||||||
|
);
|
||||||
|
|
||||||
for (const externalApiUsage of externalApiUsages) {
|
const sortedGroupNames = useMemo(() => sortGroupNames(grouped), [grouped]);
|
||||||
// Group by package if using framework mode
|
|
||||||
const key =
|
|
||||||
mode === Mode.Framework
|
|
||||||
? externalApiUsage.packageName
|
|
||||||
: externalApiUsage.library;
|
|
||||||
|
|
||||||
groupedByLibrary[key] ??= [];
|
|
||||||
groupedByLibrary[key].push(externalApiUsage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return groupedByLibrary;
|
|
||||||
}, [externalApiUsages, mode]);
|
|
||||||
|
|
||||||
const sortedGroupNames = useMemo(() => {
|
|
||||||
return Object.keys(grouped).sort((a, b) => {
|
|
||||||
const supportedPercentageA = calculateModeledPercentage(grouped[a]);
|
|
||||||
const supportedPercentageB = calculateModeledPercentage(grouped[b]);
|
|
||||||
|
|
||||||
// Sort first by supported percentage ascending
|
|
||||||
if (supportedPercentageA > supportedPercentageB) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (supportedPercentageA < supportedPercentageB) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const numberOfUsagesA = grouped[a].reduce(
|
|
||||||
(acc, curr) => acc + curr.usages.length,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
const numberOfUsagesB = grouped[b].reduce(
|
|
||||||
(acc, curr) => acc + curr.usages.length,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the number of usages is equal, sort by number of methods descending
|
|
||||||
if (numberOfUsagesA === numberOfUsagesB) {
|
|
||||||
const numberOfMethodsA = grouped[a].length;
|
|
||||||
const numberOfMethodsB = grouped[b].length;
|
|
||||||
|
|
||||||
// If the number of methods is equal, sort by library name ascending
|
|
||||||
if (numberOfMethodsA === numberOfMethodsB) {
|
|
||||||
return a.localeCompare(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return numberOfMethodsB - numberOfMethodsA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then sort by number of usages descending
|
|
||||||
return numberOfUsagesB - numberOfUsagesA;
|
|
||||||
});
|
|
||||||
}, [grouped]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { calculateModeledPercentage } from "../modeled";
|
import { calculateModeledPercentage } from "../../../../src/data-extensions-editor/shared/modeled-percentage";
|
||||||
|
|
||||||
describe("calculateModeledPercentage", () => {
|
describe("calculateModeledPercentage", () => {
|
||||||
it("when there are no external API usages", () => {
|
it("when there are no external API usages", () => {
|
||||||
Reference in New Issue
Block a user