diff --git a/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.html b/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.html
index b82be7454..51e93b411 100644
--- a/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.html
+++ b/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.html
@@ -45,11 +45,37 @@
+
+
+
+
+
+
+
diff --git a/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.ts b/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.ts
index 2113d3985..056d42047 100644
--- a/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.ts
+++ b/openhtf/output/web_gui/src/app/plugs/user-input-plug.component.ts
@@ -45,6 +45,10 @@ export declare interface UserInputPlugState {
message: string;
'text-input': string;
'image-url': string;
+ 'is-user-question': string;
+ 'button-1-text': string;
+ 'button-2-text': string;
+ 'button-3-text': string;
}
/**
@@ -99,6 +103,38 @@ export class UserInputPlugComponent extends BasePlug {
return this.getPlugState()['image-url'];
}
+ is_user_question() {
+ return (((this.getPlugState()['button-1-text'] !== null) && (this.getPlugState()['button-1-text'].length !== 0))
+ ||((this.getPlugState()['button-2-text'] !== null) && (this.getPlugState()['button-2-text'].length !== 0))
+ ||((this.getPlugState()['button-3-text'] !== null) && (this.getPlugState()['button-3-text'].length !== 0))
+ );
+ }
+
+
+ Button_1() {
+ return this.getPlugState()['button-1-text'];
+ }
+
+ Button_2() {
+ return this.getPlugState()['button-2-text'];
+ }
+
+ Button_3() {
+ return this.getPlugState()['button-3-text'];
+ }
+
+
+ sendAnswer(input: string) {
+ const promptId = this.getPlugState().id;
+ let response: string;
+ if (this.is_user_question()) {
+ response = input.trim();
+ } else {
+ response = '';
+ }
+ this.respond('respond', [promptId, response]);
+ }
+
sendResponse(input: HTMLInputElement) {
const promptId = this.getPlugState().id;
let response: string;
diff --git a/openhtf/plugs/user_input.py b/openhtf/plugs/user_input.py
index 37a21e32d..6aa5d68b2 100644
--- a/openhtf/plugs/user_input.py
+++ b/openhtf/plugs/user_input.py
@@ -59,6 +59,9 @@ class Prompt(object):
message = attr.ib(type=Text)
text_input = attr.ib(type=bool)
image_url = attr.ib(type=Optional[Text], default=None)
+ button_1_text = attr.ib(type=Optional[Text], default=None)
+ button_2_text = attr.ib(type=Optional[Text], default=None)
+ button_3_text = attr.ib(type=Optional[Text], default=None)
class ConsolePrompt(threading.Thread):
@@ -156,7 +159,11 @@ def _asdict(self) -> Optional[Dict[Text, Any]]:
return {
'id': self._prompt.id,
'message': self._prompt.message,
- 'text-input': self._prompt.text_input
+ 'text-input': self._prompt.text_input,
+ 'image-url': self._prompt.image_url,
+ 'button-1-text': self._prompt.button_1_text,
+ 'button-2-text': self._prompt.button_2_text,
+ 'button-3-text': self._prompt.button_3_text
}
def tearDown(self) -> None:
@@ -176,7 +183,10 @@ def prompt(self,
text_input: bool = False,
timeout_s: Union[int, float, None] = None,
cli_color: Text = '',
- image_url: Optional[Text] = None) -> Text:
+ image_url: Optional[Text] = None,
+ button_1_text: Optional[Text] = None,
+ button_2_text: Optional[Text] = None,
+ button_3_text: Optional[Text] = None) -> Text:
"""Display a prompt and wait for a response.
Args:
@@ -185,6 +195,7 @@ def prompt(self,
timeout_s: Seconds to wait before raising a PromptUnansweredError.
cli_color: An ANSI color code, or the empty string.
image_url: Optional image URL to display or None.
+ button_x_text: Optional. Show up to 3 buttons. The button text is returned when clicked
Returns:
A string response, or the empty string if text_input was False.
@@ -193,14 +204,17 @@ def prompt(self,
MultiplePromptsError: There was already an existing prompt.
PromptUnansweredError: Timed out waiting for the user to respond.
"""
- self.start_prompt(message, text_input, cli_color, image_url)
+ self.start_prompt(message, text_input, cli_color, image_url,button_1_text,button_2_text,button_3_text)
return self.wait_for_prompt(timeout_s)
def start_prompt(self,
message: Text,
text_input: bool = False,
cli_color: Text = '',
- image_url: Optional[Text] = None) -> Text:
+ image_url: Optional[Text] = None,
+ button_1_text: Optional[Text] = None,
+ button_2_text: Optional[Text] = None,
+ button_3_text: Optional[Text] = None) -> Text:
"""Display a prompt.
Args:
@@ -208,6 +222,7 @@ def start_prompt(self,
text_input: A boolean indicating whether the user must respond with text.
cli_color: An ANSI color code, or the empty string.
image_url: Optional image URL to display or None.
+ button_x_text: Optional. Show up to 3 buttons. The button text is returned when clicked
Raises:
MultiplePromptsError: There was already an existing prompt.
@@ -228,7 +243,10 @@ def start_prompt(self,
id=prompt_id,
message=message,
text_input=text_input,
- image_url=image_url)
+ image_url=image_url,
+ button_1_text=button_1_text,
+ button_2_text=button_2_text,
+ button_3_text=button_3_text)
if sys.stdin.isatty():
self._console_prompt = ConsolePrompt(
message, functools.partial(self.respond, prompt_id), cli_color)