diff --git a/src/components/ActionDataSamplesCard.tsx b/src/components/ActionDataSamplesCard.tsx
index fb6d74e65..d92ec41a2 100644
--- a/src/components/ActionDataSamplesCard.tsx
+++ b/src/components/ActionDataSamplesCard.tsx
@@ -21,7 +21,7 @@ import {
Text,
VStack,
} from "@chakra-ui/react";
-import { ReactNode, useCallback } from "react";
+import { forwardRef, ReactNode, useCallback, useRef } from "react";
import { RiHashtag, RiTimerLine } from "react-icons/ri";
import { FormattedMessage, useIntl } from "react-intl";
import { DataSamplesView, ActionData, RecordingData } from "../model";
@@ -81,32 +81,33 @@ const ActionDataSamplesCard = ({
)}
{value.recordings.map((recording, idx) => (
- deleteActionRecording(value.id, recording.id)}
+ />
+ }
>
- deleteActionRecording(value.id, recording.id)}
- />
-
+
))}
);
@@ -163,37 +164,58 @@ const ActionDataSamplesCard = ({
);
};
-interface DataSamplesRowCardProps extends CardProps {
- selected: boolean;
- onSelectRow?: () => void;
+interface GraphAndDataFeaturesDataSampleCardProps
+ extends DataSamplesRowCardProps {
children: ReactNode;
+ closeButton: ReactNode;
}
-const DataSamplesRowCard = ({
- selected,
- onSelectRow,
+const GraphAndDataFeaturesDataSampleCard = ({
children,
- ...rest
-}: DataSamplesRowCardProps) => {
+ closeButton,
+ ...props
+}: GraphAndDataFeaturesDataSampleCardProps) => {
+ const ref = useRef(null);
return (
-
-
- {children}
-
-
+
+ {closeButton}
+ {children}
+
);
};
+interface DataSamplesRowCardProps extends CardProps {
+ selected: boolean;
+ onSelectRow?: () => void;
+ children: ReactNode;
+}
+
+const DataSamplesRowCard = forwardRef(
+ function DataSamplesRowCard(
+ { selected, onSelectRow, children, ...rest }: DataSamplesRowCardProps,
+ ref
+ ) {
+ return (
+
+
+ {children}
+
+
+ );
+ }
+);
+
interface RecordingAreaProps extends BoxProps {
action: ActionData;
selected: boolean;
@@ -328,6 +350,7 @@ const DataSample = ({
view: DataSamplesView;
hasClose?: boolean;
}) => {
+ const ref = useRef(null);
const hasGraph =
view === DataSamplesView.Graph ||
view === DataSamplesView.GraphAndDataFeatures;
@@ -339,26 +362,27 @@ const DataSample = ({
onDelete(actionId, recording.id);
}, [actionId, onDelete, recording.id]);
return (
-
+
{hasClose && (
-
+
+
+
)}
{hasGraph && (
;
}
-const CodeViewCard = ({ project, parentRef }: CodeViewCardProps) => {
+const CodeViewCard = ({ project, parentRef, ...props }: CodeViewCardProps) => {
// This is used to set the tour cutout as the card can be taller than
// the parent in a scrollable area.
const [observableHeight, setObservableHeight] = useState(
@@ -54,7 +54,6 @@ const CodeViewCard = ({ project, parentRef }: CodeViewCardProps) => {
alignSelf="start"
display="flex"
flexDirection="column"
- py={2}
h="full"
w="full"
borderColor="brand.500"
@@ -67,6 +66,7 @@ const CodeViewCard = ({ project, parentRef }: CodeViewCardProps) => {
p={5}
objectFit="contain"
position="relative"
+ {...props}
>
{
return (
diff --git a/src/components/DataSamplesTable.tsx b/src/components/DataSamplesTable.tsx
index 2fc95fc40..8eee04edb 100644
--- a/src/components/DataSamplesTable.tsx
+++ b/src/components/DataSamplesTable.tsx
@@ -36,15 +36,12 @@ const gridCommonProps: Partial = {
};
const headings: GridColumnHeadingItemProps[] = [
- {
- titleId: "action-label",
- descriptionId: "action-tooltip",
- },
+ { titleId: "action-label", descriptionId: "action-tooltip" },
{
titleId: "data-samples-label",
descriptionId: "data-samples-tooltip",
itemsRight: (
-
+
@@ -245,10 +242,9 @@ const DataSamplesTable = ({
>
)}
0 ? `${gridPadding}px` : 2}
alignItems="start"
autoRows="max-content"
- overflow="auto"
flexGrow={1}
h={0}
ref={(node) => {
diff --git a/src/components/HeadingGrid.tsx b/src/components/HeadingGrid.tsx
index 8e5d6d092..e348b0600 100644
--- a/src/components/HeadingGrid.tsx
+++ b/src/components/HeadingGrid.tsx
@@ -11,15 +11,18 @@ import { ReactNode } from "react";
interface HeadingGridProps extends GridProps {
headings: GridColumnHeadingItemProps[];
}
-
const HeadingGrid = ({ headings, ...props }: HeadingGridProps) => {
return (
{headings.map((props, idx) => (
diff --git a/src/components/TestingModelTable.tsx b/src/components/TestingModelTable.tsx
index e8bc39838..a96981df4 100644
--- a/src/components/TestingModelTable.tsx
+++ b/src/components/TestingModelTable.tsx
@@ -6,15 +6,15 @@
*/
import {
Box,
+ Flex,
Grid,
GridItem,
GridProps,
- HStack,
Icon,
VStack,
} from "@chakra-ui/react";
import { MakeCodeRenderBlocksProvider } from "@microbit/makecode-embed/react";
-import { useRef } from "react";
+import { useEffect, useRef, useState } from "react";
import { RiArrowRightLine } from "react-icons/ri";
import { useIntl } from "react-intl";
import { useDataConnected } from "../data-connection-flow";
@@ -28,9 +28,12 @@ import CodeViewCard from "./CodeViewCard";
import CodeViewDefaultBlockCard from "./CodeViewDefaultBlockCard";
import HeadingGrid from "./HeadingGrid";
+const blockCardMinWidth = "400px";
+const gap = 3;
+
const gridCommonProps: Partial = {
- gridTemplateColumns: "290px 360px 40px auto",
- gap: 3,
+ gridTemplateColumns: `290px 360px 40px minmax(${blockCardMinWidth}, 1fr)`,
+ gap,
w: "100%",
};
@@ -58,82 +61,129 @@ const TestingModelTable = () => {
const isConnected = useDataConnected();
const [{ languageId }] = useSettings();
const makeCodeLang = getMakeCodeLang(languageId);
- const scrollableAreaRef = useRef(null);
+ const gridAreaRef = useRef(null);
const intl = useIntl();
+
+ const scrollableAreaRef = useRef(null);
+ const [scrollbarWidth, setScrollbarWidth] = useState(0);
+ useEffect(() => {
+ const scrollEl = scrollableAreaRef.current;
+ if (!scrollEl) {
+ return;
+ }
+ const measure = () => {
+ const hasScrollbar = scrollEl.scrollHeight > scrollEl.clientHeight;
+ const scrollbarWidth = scrollEl.offsetWidth - scrollEl.clientWidth;
+ setScrollbarWidth(hasScrollbar ? scrollbarWidth : 0);
+ };
+
+ measure(); // run on mount.
+ window.addEventListener("resize", measure);
+ return () => window.removeEventListener("resize", measure);
+ }, []);
+
return (
-
-
-
-
+
+
- {actions.map((action) => {
- const { requiredConfidence: threshold } = action;
- return (
-
-
-
-
-
-
- setRequiredConfidence(action.id, val)
- }
- requiredConfidence={
- threshold ?? mlSettings.defaultRequiredConfidence
- }
- disabled={!isConnected}
- />
-
-
-
-
-
+
+ {actions.map((action, actionIdx) => {
+ const { requiredConfidence: threshold } = action;
+ return (
+
+
+
+
+
+
+ setRequiredConfidence(action.id, val)
+ }
+ requiredConfidence={
+ threshold ?? mlSettings.defaultRequiredConfidence
+ }
+ disabled={!isConnected}
+ />
+
+
+
+
{!projectEdited && (
-
+
+
+
+ )}
+
+ {projectEdited && actionIdx === 0 && (
+
+
+
)}
-
-
- );
- })}
-
- {projectEdited && (
-
- )}
-
-
+
+ );
+ })}
+
+
+
+
);
};
diff --git a/src/pages/DataSamplesPage.tsx b/src/pages/DataSamplesPage.tsx
index ec9de390f..482bf75dd 100644
--- a/src/pages/DataSamplesPage.tsx
+++ b/src/pages/DataSamplesPage.tsx
@@ -288,7 +288,13 @@ const DataSamplesPage = () => {
}
backLabelId="home-action"
>
-
+