Make libraries collapsible

This commit is contained in:
Koen Vlaswinkel
2023-06-19 15:58:33 +02:00
parent a833f78151
commit 768c10734e
4 changed files with 129 additions and 16 deletions

View File

@@ -16,6 +16,7 @@ import { basename } from "../common/path";
import { ViewTitle } from "../common";
import { DataExtensionEditorViewState } from "../../data-extensions-editor/shared/view-state";
import { ModeledMethodsList } from "./ModeledMethodsList";
import { percentFormatter } from "./formatters";
const DataExtensionsEditorContainer = styled.div`
margin-top: 1rem;
@@ -213,8 +214,12 @@ export function DataExtensionsEditor({
)}
</>
)}
<div>{modeledPercentage.toFixed(2)}% modeled</div>
<div>{unModeledPercentage.toFixed(2)}% unmodeled</div>
<div>
{percentFormatter.format(modeledPercentage / 100)} modeled
</div>
<div>
{percentFormatter.format(unModeledPercentage / 100)} unmodeled
</div>
</DetailsContainer>
<EditorContainer>

View File

@@ -0,0 +1,105 @@
import * as React from "react";
import { useCallback, useMemo, useState } from "react";
import styled from "styled-components";
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
import { ModeledMethodDataGrid } from "./ModeledMethodDataGrid";
import { calculateModeledPercentage } from "./modeled";
import { decimalFormatter, percentFormatter } from "./formatters";
const LibraryContainer = styled.div`
margin-bottom: 1rem;
`;
const TitleContainer = styled.button`
display: flex;
gap: 0.5em;
align-items: center;
width: 100%;
font-size: 1.2em;
font-weight: bold;
color: var(--vscode-editor-foreground);
background-color: transparent;
border: none;
cursor: pointer;
`;
const StatusContainer = styled.div`
display: flex;
gap: 1em;
align-items: center;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 1em;
`;
type Props = {
libraryName: string;
externalApiUsages: ExternalApiUsage[];
modeledMethods: Record<string, ModeledMethod>;
onChange: (
externalApiUsage: ExternalApiUsage,
modeledMethod: ModeledMethod,
) => void;
};
export const LibraryRow = ({
libraryName,
externalApiUsages,
modeledMethods,
onChange,
}: Props) => {
const modeledPercentage = useMemo(() => {
return calculateModeledPercentage(externalApiUsages);
}, [externalApiUsages]);
const [isExpanded, setExpanded] = useState(modeledPercentage < 100);
const toggleExpanded = useCallback(async () => {
setExpanded((oldIsExpanded) => !oldIsExpanded);
}, []);
const usagesCount = useMemo(() => {
return externalApiUsages.reduce((acc, curr) => acc + curr.usages.length, 0);
}, [externalApiUsages]);
return (
<LibraryContainer>
<TitleContainer onClick={toggleExpanded} aria-expanded={isExpanded}>
{libraryName}
{isExpanded ? null : (
<>
{" "}
({decimalFormatter.format(externalApiUsages.length)} method
{externalApiUsages.length !== 1 ? "s" : ""},{" "}
{percentFormatter.format(modeledPercentage / 100)} modeled)
</>
)}
</TitleContainer>
{isExpanded && (
<>
<StatusContainer>
<div>
{decimalFormatter.format(externalApiUsages.length)} method
{externalApiUsages.length !== 1 ? "s" : ""}
</div>
<div>
{decimalFormatter.format(usagesCount)} usage
{usagesCount !== 1 ? "s" : ""}
</div>
<div>
{percentFormatter.format(modeledPercentage / 100)} modeled
</div>
</StatusContainer>
<ModeledMethodDataGrid
externalApiUsages={externalApiUsages}
modeledMethods={modeledMethods}
onChange={onChange}
/>
</>
)}
</LibraryContainer>
);
};

View File

@@ -1,14 +1,9 @@
import * as React from "react";
import { useMemo } from "react";
import styled from "styled-components";
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
import { ModeledMethodDataGrid } from "./ModeledMethodDataGrid";
import { calculateModeledPercentage } from "./modeled";
const LibraryContainer = styled.div`
margin-bottom: 1rem;
`;
import { LibraryRow } from "./LibraryRow";
type Props = {
externalApiUsages: ExternalApiUsage[];
@@ -69,14 +64,13 @@ export const ModeledMethodsList = ({
return (
<>
{sortedLibraryNames.map((libraryName) => (
<LibraryContainer key={libraryName}>
<h3>{libraryName}</h3>
<ModeledMethodDataGrid
<LibraryRow
key={libraryName}
libraryName={libraryName}
externalApiUsages={groupedByLibrary[libraryName]}
modeledMethods={modeledMethods}
onChange={onChange}
/>
</LibraryContainer>
))}
</>
);

View File

@@ -0,0 +1,9 @@
export const decimalFormatter = new Intl.NumberFormat("en-US", {
style: "decimal",
maximumFractionDigits: 2,
});
export const percentFormatter = new Intl.NumberFormat("en-US", {
style: "percent",
maximumFractionDigits: 2,
});