File size: 2,757 Bytes
9b906ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import type { MouseEvent, RefObject } from "react";
import { useTranslation } from "react-i18next";
import { useClickOutsideElement } from "#/hooks/use-click-outside-element";
import { ContextMenu } from "#/ui/context-menu";
import { I18nKey } from "#/i18n/declaration";
import StopCircleIcon from "#/icons/stop-circle.svg?react";
import PlayCircleIcon from "#/icons/play-circle.svg?react";
import { ServerStatusContextMenuIconText } from "./server-status-context-menu-icon-text";
import { ServerStatus } from "./server-status";
import { Divider } from "#/ui/divider";
import { cn } from "#/utils/utils";
import { ExecutionStatus } from "#/types/agent-server/core/base/common";
import { isExecutionActive, isExecutionPaused } from "#/utils/status";

interface ServerStatusContextMenuProps {
  onClose: () => void;
  onStopServer?: (event: MouseEvent<HTMLButtonElement>) => void;
  onStartServer?: (event: MouseEvent<HTMLButtonElement>) => void;
  executionStatus: ExecutionStatus | null;
  position?: "top" | "bottom";
  className?: string;
  isPausing?: boolean;
  ignoreOutsideClickRef?: RefObject<HTMLElement | null>;
}

export function ServerStatusContextMenu({
  onClose,
  onStopServer,
  onStartServer,
  executionStatus,
  position = "top",
  className = "",
  isPausing = false,
  ignoreOutsideClickRef,
}: ServerStatusContextMenuProps) {
  const { t } = useTranslation("openhands");
  const ref = useClickOutsideElement<HTMLUListElement>(
    onClose,
    ignoreOutsideClickRef,
  );

  const isActive = isExecutionActive(executionStatus);
  const isPaused = isExecutionPaused(executionStatus);
  const shouldActionShown = isActive || isPaused;

  return (
    <ContextMenu
      ref={ref}
      testId="server-status-context-menu"
      position={position}
      alignment="left"
      size="default"
      className={cn("left-2 w-fit min-w-42", className)}
    >
      <ServerStatus
        executionStatus={executionStatus}
        isPausing={isPausing}
        className="pl-0 pr-2 py-1"
      />

      {shouldActionShown && (
        <>
          <Divider inset="menu" />

          {isActive && onStopServer && (
            <ServerStatusContextMenuIconText
              icon={<StopCircleIcon width={18} height={18} />}
              text={t(I18nKey.COMMON$STOP_RUNTIME)}
              onClick={onStopServer}
              testId="stop-server-button"
            />
          )}

          {isPaused && onStartServer && (
            <ServerStatusContextMenuIconText
              icon={<PlayCircleIcon width={18} height={18} />}
              text={t(I18nKey.COMMON$START_RUNTIME)}
              onClick={onStartServer}
              testId="start-server-button"
            />
          )}
        </>
      )}
    </ContextMenu>
  );
}