Skip to content

Commit

Permalink
Improve service button (response in tooltip)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafal-gorecki committed Aug 26, 2024
1 parent 44c70b2 commit 177bb01
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 46 deletions.
4 changes: 2 additions & 2 deletions packages/studio-base/src/i18n/en/panels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export const panels = {
teleopDescription: "Teleoperate a robot over a live connection.",
topicGraph: "Topic Graph",
topicGraphDescription: "Display a graph of active nodes, topics, and services.",
triggerButton: "Custom: Trigger Button",
triggerButtonDescription: "Button to call std_srvs/Trigger.",
serviceButton: "Custom: Service Button",
serviceButtonDescription: "Button to call std_srvs/Trigger.",
userScripts: "User Scripts",
userScriptsDescription:
"Write custom data transformations in TypeScript. Previously known as Node Playground.",
Expand Down
2 changes: 1 addition & 1 deletion packages/studio-base/src/panels/EStop/EStop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ function EStopContent(
borderRadius: "0.3rem",
}}
>
{eStopAction?.toUpperCase() ?? "Wait for feedback"}
{eStopAction?.toUpperCase() ?? "Waiting..."}
</Button>
</span>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { makeStyles } from "tss-react/mui";
import Log from "@foxglove/log";
import { PanelExtensionContext, SettingsTreeAction } from "@foxglove/studio";
import Stack from "@foxglove/studio-base/components/Stack";
import { Config } from "@foxglove/studio-base/panels/TriggerButton/types";
import { Config } from "@foxglove/studio-base/panels/ServiceButton/types";
import ThemeProvider from "@foxglove/studio-base/theme/ThemeProvider";

import { defaultConfig, settingsActionReducer, useSettingsTree } from "./settings";
Expand Down Expand Up @@ -88,17 +88,17 @@ function parseInput(value: string): { error?: string; parsedObject?: unknown } {
}

// Wrapper component with ThemeProvider so useStyles in the panel receives the right theme.
export function TriggerButton({ context }: Props): JSX.Element {
export function ServiceButton({ context }: Props): JSX.Element {
const [colorScheme, setColorScheme] = useState<Palette["mode"]>("light");

return (
<ThemeProvider isDark={colorScheme === "dark"}>
<TriggerButtonContent context={context} setColorScheme={setColorScheme} />
<ServiceButtonContent context={context} setColorScheme={setColorScheme} />
</ThemeProvider>
);
}

function TriggerButtonContent(
function ServiceButtonContent(
props: Props & { setColorScheme: Dispatch<SetStateAction<Palette["mode"]>> },
): JSX.Element {
const { context, setColorScheme } = props;
Expand Down Expand Up @@ -163,15 +163,15 @@ function TriggerButtonContent(
return undefined;
}, [context, config.serviceName]);

const canTriggerButton = Boolean(
const canServiceButton = Boolean(
context.callService != undefined &&
config.requestPayload &&
config.serviceName &&
parsedObject != undefined &&
state?.status !== "requesting",
);

const triggerButtonClicked = useCallback(async () => {
const serviceButtonClicked = useCallback(async () => {
if (!context.callService) {
setState({ status: "error", value: "The data source does not allow calling services" });
return;
Expand Down Expand Up @@ -263,13 +263,13 @@ function TriggerButtonContent(
{statusMessage}
</Typography>
)}
<Tooltip title={config.buttonTooltip}>
<Tooltip title={config.buttonTooltip ? config.buttonTooltip : state?.value}>
<span>
<Button
className={classes.button}
variant="contained"
disabled={!canTriggerButton}
onClick={triggerButtonClicked}
disabled={!canServiceButton}
onClick={serviceButtonClicked}
data-testid="call-service-button"
style={{
minWidth: "200px",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PlayerCapabilities } from "@foxglove/studio-base/players/types";
import PanelSetup, { Fixture } from "@foxglove/studio-base/stories/PanelSetup";
import delay from "@foxglove/studio-base/util/delay";

import TriggerButtonPanel from "./index";
import ServiceButtonPanel from "./index";
import { Config } from "./types";

const successResponseJson = JSON.stringify({ success: true }, undefined, 2);
Expand All @@ -19,8 +19,8 @@ const baseConfig: Config = {
requestPayload: `{\n "data": true\n}`,
};

const getFixture = ({ allowTriggerButton }: { allowTriggerButton: boolean }): Fixture => {
const triggerButton = async (service: string, _request: unknown) => {
const getFixture = ({ allowServiceButton }: { allowServiceButton: boolean }): Fixture => {
const serviceButton = async (service: string, _request: unknown) => {
if (service !== baseConfig.serviceName) {
throw new Error(`Service "${service}" does not exist`);
}
Expand All @@ -35,14 +35,14 @@ const getFixture = ({ allowTriggerButton }: { allowTriggerButton: boolean }): Fi
}),
),
frame: {},
capabilities: allowTriggerButton ? [PlayerCapabilities.triggerButtons] : [],
triggerButton,
capabilities: allowServiceButton ? [PlayerCapabilities.serviceButtons] : [],

Check failure on line 38 in packages/studio-base/src/panels/ServiceButton/index.stories.tsx

View workflow job for this annotation

GitHub Actions / packages (ubuntu-20.04)

Property 'serviceButtons' does not exist on type '{ advertise: string; assets: string; callServices: string; setSpeed: string; playbackControl: string; getParameters: string; setParameters: string; }'.
serviceButton,

Check failure on line 39 in packages/studio-base/src/panels/ServiceButton/index.stories.tsx

View workflow job for this annotation

GitHub Actions / packages (ubuntu-20.04)

Object literal may only specify known properties, and 'serviceButton' does not exist in type 'Fixture'.
};
};

export default {
title: "panels/TriggerButton",
component: TriggerButtonPanel,
title: "panels/ServiceButton",
component: ServiceButtonPanel,
parameters: {
colorScheme: "both-column",
},
Expand All @@ -59,27 +59,27 @@ export default {

export const Default: StoryObj = {
render: () => {
return <TriggerButtonPanel />;
return <ServiceButtonPanel />;
},
};

export const DefaultHorizontalLayout: StoryObj = {
render: () => {
return <TriggerButtonPanel overrideConfig={{ layout: "horizontal" }} />;
return <ServiceButtonPanel overrideConfig={{ layout: "horizontal" }} />;
},
};

export const TriggerButtonEnabled: StoryObj = {
export const ServiceButtonEnabled: StoryObj = {
render: () => {
return <TriggerButtonPanel />;
return <ServiceButtonPanel />;
},

parameters: { panelSetup: { fixture: getFixture({ allowTriggerButton: true }) } },
parameters: { panelSetup: { fixture: getFixture({ allowServiceButton: true }) } },
};

export const TriggerButtonEnabledServiceName: StoryObj = {
export const ServiceButtonEnabledServiceName: StoryObj = {
render: () => {
return <TriggerButtonPanel overrideConfig={{ ...baseConfig }} />;
return <ServiceButtonPanel overrideConfig={{ ...baseConfig }} />;
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
Expand All @@ -94,13 +94,13 @@ export const TriggerButtonEnabledServiceName: StoryObj = {
}
},

parameters: { panelSetup: { fixture: getFixture({ allowTriggerButton: true }) } },
parameters: { panelSetup: { fixture: getFixture({ allowServiceButton: true }) } },
};

export const TriggerButtonEnabledWithCustomButtonSettings: StoryObj = {
export const ServiceButtonEnabledWithCustomButtonSettings: StoryObj = {
render: () => {
return (
<TriggerButtonPanel
<ServiceButtonPanel
overrideConfig={{
...baseConfig,
buttonColor: "#ffbf49",
Expand All @@ -118,29 +118,29 @@ export const TriggerButtonEnabledWithCustomButtonSettings: StoryObj = {
});
},

parameters: { panelSetup: { fixture: getFixture({ allowTriggerButton: true }) } },
parameters: { panelSetup: { fixture: getFixture({ allowServiceButton: true }) } },
};

const validJSON = `{\n "a": 1,\n "b": 2,\n "c": 3\n}`;

export const WithValidJSON: StoryObj = {
render: () => {
return <TriggerButtonPanel overrideConfig={{ ...baseConfig, requestPayload: validJSON }} />;
return <ServiceButtonPanel overrideConfig={{ ...baseConfig, requestPayload: validJSON }} />;
},
};

const invalidJSON = `{\n "a": 1,\n 'b: 2,\n "c": 3\n}`;

export const WithInvalidJSON: StoryObj = {
render: () => {
return <TriggerButtonPanel overrideConfig={{ ...baseConfig, requestPayload: invalidJSON }} />;
return <ServiceButtonPanel overrideConfig={{ ...baseConfig, requestPayload: invalidJSON }} />;
},
};

export const CallingServiceThatDoesNotExist: StoryObj = {
render: () => {
return (
<TriggerButtonPanel
<ServiceButtonPanel
overrideConfig={{
...baseConfig,
serviceName: "/non_existing_service",
Expand All @@ -161,5 +161,5 @@ export const CallingServiceThatDoesNotExist: StoryObj = {
}
},

parameters: { panelSetup: { fixture: getFixture({ allowTriggerButton: true }) } },
parameters: { panelSetup: { fixture: getFixture({ allowServiceButton: true }) } },
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import Panel from "@foxglove/studio-base/components/Panel";
import { PanelExtensionAdapter } from "@foxglove/studio-base/components/PanelExtensionAdapter";
import { SaveConfig } from "@foxglove/studio-base/types/panels";

import { TriggerButton } from "./TriggerButton";
import { ServiceButton } from "./ServiceButton";
import { Config } from "./types";

function initPanel(crash: ReturnType<typeof useCrash>, context: PanelExtensionContext) {
// eslint-disable-next-line react/no-deprecated
ReactDOM.render(
<StrictMode>
<CaptureErrorBoundary onError={crash}>
<TriggerButton context={context} />
<ServiceButton context={context} />
</CaptureErrorBoundary>
</StrictMode>,
context.panelElement,
Expand All @@ -36,7 +36,7 @@ type Props = {
saveConfig: SaveConfig<Config>;
};

function TriggerButtonPanelAdapter(props: Props) {
function ServiceButtonPanelAdapter(props: Props) {
const crash = useCrash();
const boundInitPanel = useMemo(() => initPanel.bind(undefined, crash), [crash]);

Expand All @@ -50,7 +50,7 @@ function TriggerButtonPanelAdapter(props: Props) {
);
}

TriggerButtonPanelAdapter.panelType = "TriggerButton";
TriggerButtonPanelAdapter.defaultConfig = {};
ServiceButtonPanelAdapter.panelType = "ServiceButton";
ServiceButtonPanelAdapter.defaultConfig = {};

export default Panel(TriggerButtonPanelAdapter);
export default Panel(ServiceButtonPanelAdapter);
12 changes: 6 additions & 6 deletions packages/studio-base/src/panels/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import parametersThumbnail from "./Parameters/thumbnail.png";
import plotThumbnail from "./Plot/thumbnail.png";
import publishThumbnail from "./Publish/thumbnail.png";
import rawMessagesThumbnail from "./RawMessages/thumbnail.png";
import serviceButtonThumbnail from "./ServiceButton/thumbnail.png";
import stateTransitionsThumbnail from "./StateTransitions/thumbnail.png";
import tabThumbnail from "./Tab/thumbnail.png";
import tableThumbnail from "./Table/thumbnail.png";
import teleopThumbnail from "./Teleop/thumbnail.png";
import threeDeeRenderThumbnail from "./ThreeDeeRender/thumbnail.png";
import topicGraphThumbnail from "./TopicGraph/thumbnail.png";
import triggerButtonThumbnail from "./TriggerButton/thumbnail.png";
import variableSliderThumbnail from "./VariableSlider/thumbnail.png";
import diagnosticStatusThumbnail from "./diagnostics/thumbnails/diagnostic-status.png";
import diagnosticSummaryThumbnail from "./diagnostics/thumbnails/diagnostic-summary.png";
Expand Down Expand Up @@ -199,11 +199,11 @@ export const getBuiltin: (t: TFunction<"panels">) => PanelInfo[] = (t) => [
hasCustomToolbar: true,
},
{
title: t("triggerButton"),
type: "TriggerButton",
description: t("triggerButtonDescription"),
thumbnail: triggerButtonThumbnail,
module: async () => await import("./TriggerButton"),
title: t("serviceButton"),
type: "ServiceButton",
description: t("serviceButtonDescription"),
thumbnail: serviceButtonThumbnail,
module: async () => await import("./ServiceButton"),
},
{
title: t("eStop"),
Expand Down

0 comments on commit 177bb01

Please sign in to comment.