david-oplatka
commited on
Commit
·
684067e
1
Parent(s):
9cdc5d0
Add refs for rerendering components
Browse files- app.py +0 -1
- chatbox.py +108 -21
- chatui.py +9 -5
- footer.py +142 -6
- header.py +47 -37
app.py
CHANGED
@@ -31,7 +31,6 @@ def App():
|
|
31 |
set_agent_log_entries([])
|
32 |
|
33 |
def add_log_entry(new_log_entry):
|
34 |
-
print(f"ADDING LOG ENTRY {new_log_entry}")
|
35 |
set_agent_log_entries(lambda previous_entries: previous_entries + [new_log_entry])
|
36 |
|
37 |
return agent_log_entries, add_log_entry, reset_log_entries
|
|
|
31 |
set_agent_log_entries([])
|
32 |
|
33 |
def add_log_entry(new_log_entry):
|
|
|
34 |
set_agent_log_entries(lambda previous_entries: previous_entries + [new_log_entry])
|
35 |
|
36 |
return agent_log_entries, add_log_entry, reset_log_entries
|
chatbox.py
CHANGED
@@ -2,15 +2,34 @@ from reactpy import component, html, svg
|
|
2 |
from reactpy.core.hooks import use_ref
|
3 |
|
4 |
@component
|
5 |
-
# def ChatBox(message, set_message, handle_input_change, handle_key_down, send_message, collapsed):
|
6 |
def ChatBox(message, set_message, send_message, collapsed):
|
7 |
-
|
|
|
8 |
def handle_input_change(event):
|
|
|
9 |
set_message(event['target']['value'])
|
10 |
-
|
11 |
def handle_key_down(event):
|
|
|
12 |
if event['key'] == 'Enter' and message.strip():
|
13 |
send_message()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
return html.div(
|
16 |
{
|
@@ -51,7 +70,7 @@ def ChatBox(message, set_message, send_message, collapsed):
|
|
51 |
"position": "absolute",
|
52 |
"right": "8px",
|
53 |
"top": "50%",
|
54 |
-
"transform":"translateY(-50%)",
|
55 |
"background": "none",
|
56 |
"border": "none",
|
57 |
"cursor": "pointer",
|
@@ -61,21 +80,89 @@ def ChatBox(message, set_message, send_message, collapsed):
|
|
61 |
"justifyContent": "center",
|
62 |
}
|
63 |
},
|
64 |
-
|
65 |
-
{
|
66 |
-
"xmlns": "http://www.w3.org/2000/svg",
|
67 |
-
"width": "20",
|
68 |
-
"height": "20",
|
69 |
-
"fill": "none",
|
70 |
-
"stroke": "currentColor",
|
71 |
-
"stroke-linecap": "round",
|
72 |
-
"stroke-linejoin": "round",
|
73 |
-
"stroke-width": "2",
|
74 |
-
"viewBox": "0 0 24 24",
|
75 |
-
"class": "feather feather-send",
|
76 |
-
},
|
77 |
-
svg.path({"d": "M22 2 11 13"}),
|
78 |
-
svg.path({"d": "M22 2 15 22 11 13 2 9z"})
|
79 |
-
)
|
80 |
)
|
81 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
from reactpy.core.hooks import use_ref
|
3 |
|
4 |
@component
|
|
|
5 |
def ChatBox(message, set_message, send_message, collapsed):
|
6 |
+
# Store the static SVG button in a ref so it doesn't re-render unnecessarily
|
7 |
+
send_button_ref = use_ref(None)
|
8 |
def handle_input_change(event):
|
9 |
+
# Update the message state when input changes
|
10 |
set_message(event['target']['value'])
|
|
|
11 |
def handle_key_down(event):
|
12 |
+
# Check for Enter key and send message if the message is not empty
|
13 |
if event['key'] == 'Enter' and message.strip():
|
14 |
send_message()
|
15 |
+
# Only define the static button SVG once
|
16 |
+
if send_button_ref.current is None:
|
17 |
+
send_button_ref.current = svg.svg(
|
18 |
+
{
|
19 |
+
"xmlns": "http://www.w3.org/2000/svg",
|
20 |
+
"width": "20",
|
21 |
+
"height": "20",
|
22 |
+
"fill": "none",
|
23 |
+
"stroke": "currentColor",
|
24 |
+
"stroke-linecap": "round",
|
25 |
+
"stroke-linejoin": "round",
|
26 |
+
"stroke-width": "2",
|
27 |
+
"viewBox": "0 0 24 24",
|
28 |
+
"class": "feather feather-send",
|
29 |
+
},
|
30 |
+
svg.path({"d": "M22 2 11 13"}),
|
31 |
+
svg.path({"d": "M22 2 15 22 11 13 2 9z"})
|
32 |
+
)
|
33 |
|
34 |
return html.div(
|
35 |
{
|
|
|
70 |
"position": "absolute",
|
71 |
"right": "8px",
|
72 |
"top": "50%",
|
73 |
+
"transform": "translateY(-50%)",
|
74 |
"background": "none",
|
75 |
"border": "none",
|
76 |
"cursor": "pointer",
|
|
|
80 |
"justifyContent": "center",
|
81 |
}
|
82 |
},
|
83 |
+
send_button_ref.current # Render the cached send button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
)
|
85 |
+
)
|
86 |
+
|
87 |
+
|
88 |
+
# from reactpy import component, html, svg
|
89 |
+
# from reactpy.core.hooks import use_ref
|
90 |
+
|
91 |
+
# @component
|
92 |
+
# # def ChatBox(message, set_message, handle_input_change, handle_key_down, send_message, collapsed):
|
93 |
+
# def ChatBox(message, set_message, send_message, collapsed):
|
94 |
+
|
95 |
+
# def handle_input_change(event):
|
96 |
+
# set_message(event['target']['value'])
|
97 |
+
|
98 |
+
# def handle_key_down(event):
|
99 |
+
# if event['key'] == 'Enter' and message.strip():
|
100 |
+
# send_message()
|
101 |
+
|
102 |
+
# return html.div(
|
103 |
+
# {
|
104 |
+
# "style": {
|
105 |
+
# "position": "fixed",
|
106 |
+
# "bottom": "70px" if collapsed else "140px",
|
107 |
+
# "left": "50%",
|
108 |
+
# "transform": "translateX(-50%)",
|
109 |
+
# "width": "80%",
|
110 |
+
# "display": "flex",
|
111 |
+
# "alignItems": "center",
|
112 |
+
# "backgroundColor": "#FFFFFF",
|
113 |
+
# "borderRadius": "50px",
|
114 |
+
# "zIndex": "1000",
|
115 |
+
# }
|
116 |
+
# },
|
117 |
+
# html.input(
|
118 |
+
# {
|
119 |
+
# "type": "text",
|
120 |
+
# "value": message,
|
121 |
+
# "placeholder": "Your Message",
|
122 |
+
# "onChange": handle_input_change,
|
123 |
+
# "onKeyDown": handle_key_down,
|
124 |
+
# "style": {
|
125 |
+
# "width": "100%",
|
126 |
+
# "padding": "10px 50px 10px 20px",
|
127 |
+
# "border": "none",
|
128 |
+
# "borderRadius": "50px",
|
129 |
+
# "color": "#65558F",
|
130 |
+
# }
|
131 |
+
# }
|
132 |
+
# ),
|
133 |
+
# html.button(
|
134 |
+
# {
|
135 |
+
# "type": "button",
|
136 |
+
# "onClick": send_message,
|
137 |
+
# "style": {
|
138 |
+
# "position": "absolute",
|
139 |
+
# "right": "8px",
|
140 |
+
# "top": "50%",
|
141 |
+
# "transform":"translateY(-50%)",
|
142 |
+
# "background": "none",
|
143 |
+
# "border": "none",
|
144 |
+
# "cursor": "pointer",
|
145 |
+
# "padding": "8px",
|
146 |
+
# "display": "flex",
|
147 |
+
# "alignItems": "center",
|
148 |
+
# "justifyContent": "center",
|
149 |
+
# }
|
150 |
+
# },
|
151 |
+
# svg.svg(
|
152 |
+
# {
|
153 |
+
# "xmlns": "http://www.w3.org/2000/svg",
|
154 |
+
# "width": "20",
|
155 |
+
# "height": "20",
|
156 |
+
# "fill": "none",
|
157 |
+
# "stroke": "currentColor",
|
158 |
+
# "stroke-linecap": "round",
|
159 |
+
# "stroke-linejoin": "round",
|
160 |
+
# "stroke-width": "2",
|
161 |
+
# "viewBox": "0 0 24 24",
|
162 |
+
# "class": "feather feather-send",
|
163 |
+
# },
|
164 |
+
# svg.path({"d": "M22 2 11 13"}),
|
165 |
+
# svg.path({"d": "M22 2 15 22 11 13 2 9z"})
|
166 |
+
# )
|
167 |
+
# )
|
168 |
+
# )
|
chatui.py
CHANGED
@@ -2,6 +2,7 @@ from markdown_it import MarkdownIt
|
|
2 |
from mdit_py_plugins import front_matter
|
3 |
|
4 |
from reactpy import component, html
|
|
|
5 |
|
6 |
from utils import wait_message
|
7 |
|
@@ -51,8 +52,10 @@ def ExamplePrompts(examples, send_example, first_turn):
|
|
51 |
question
|
52 |
)
|
53 |
|
54 |
-
|
55 |
-
|
|
|
|
|
56 |
{
|
57 |
"style": {
|
58 |
"display": "flex",
|
@@ -86,6 +89,9 @@ def ExamplePrompts(examples, send_example, first_turn):
|
|
86 |
*[create_prompt_button(q) for q in example_questions]
|
87 |
)
|
88 |
)
|
|
|
|
|
|
|
89 |
|
90 |
return None
|
91 |
|
@@ -118,9 +124,7 @@ def ChatMessage(user, message):
|
|
118 |
|
119 |
@component
|
120 |
def Logs(messages, log_entries, show_logs, set_show_logs, show_logs_button):
|
121 |
-
|
122 |
-
# print(f"DEBUG: LENGTH OF LOG MESSAGES IS {len(log_entries)}")
|
123 |
-
# print(f"DEBUG: SHOW LOGS BUTTON IS {show_logs_button}")
|
124 |
if (len(messages) > 0) and (len(log_entries) > 0) and (messages[-1]["message"] != wait_message) and (show_logs_button):
|
125 |
if not show_logs:
|
126 |
return html.div(
|
|
|
2 |
from mdit_py_plugins import front_matter
|
3 |
|
4 |
from reactpy import component, html
|
5 |
+
from reactpy.core.hooks import use_ref
|
6 |
|
7 |
from utils import wait_message
|
8 |
|
|
|
52 |
question
|
53 |
)
|
54 |
|
55 |
+
examples_ref = use_ref(None)
|
56 |
+
|
57 |
+
if examples_ref.current is None:
|
58 |
+
examples_ref.current = html.div(
|
59 |
{
|
60 |
"style": {
|
61 |
"display": "flex",
|
|
|
89 |
*[create_prompt_button(q) for q in example_questions]
|
90 |
)
|
91 |
)
|
92 |
+
|
93 |
+
if first_turn:
|
94 |
+
return examples_ref.current
|
95 |
|
96 |
return None
|
97 |
|
|
|
124 |
|
125 |
@component
|
126 |
def Logs(messages, log_entries, show_logs, set_show_logs, show_logs_button):
|
127 |
+
|
|
|
|
|
128 |
if (len(messages) > 0) and (len(log_entries) > 0) and (messages[-1]["message"] != wait_message) and (show_logs_button):
|
129 |
if not show_logs:
|
130 |
return html.div(
|
footer.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1 |
-
from reactpy import component, html, svg, hooks
|
|
|
2 |
|
3 |
@component
|
4 |
def Footer(collapsed, set_collapsed):
|
5 |
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
8 |
{
|
9 |
"style": {
|
10 |
"backgroundColor": "#FFFFFF",
|
@@ -44,8 +48,9 @@ def Footer(collapsed, set_collapsed):
|
|
44 |
)
|
45 |
)
|
46 |
)
|
47 |
-
|
48 |
-
|
|
|
49 |
{
|
50 |
"style": {
|
51 |
"backgroundColor": "#FFFFFF",
|
@@ -119,4 +124,135 @@ def Footer(collapsed, set_collapsed):
|
|
119 |
"It demonstrates the use of Agentic-RAG functionality with Vectara",
|
120 |
)
|
121 |
)
|
122 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from reactpy import component, html, svg, hooks
|
2 |
+
from reactpy.core.hooks import use_ref
|
3 |
|
4 |
@component
|
5 |
def Footer(collapsed, set_collapsed):
|
6 |
|
7 |
+
expanded_footer_ref = use_ref(None)
|
8 |
+
collapsed_footer_ref = use_ref(None)
|
9 |
+
|
10 |
+
if expanded_footer_ref.current is None:
|
11 |
+
expanded_footer_ref.current = html.footer(
|
12 |
{
|
13 |
"style": {
|
14 |
"backgroundColor": "#FFFFFF",
|
|
|
48 |
)
|
49 |
)
|
50 |
)
|
51 |
+
|
52 |
+
if collapsed_footer_ref.current is None:
|
53 |
+
collapsed_footer_ref.current = html.footer(
|
54 |
{
|
55 |
"style": {
|
56 |
"backgroundColor": "#FFFFFF",
|
|
|
124 |
"It demonstrates the use of Agentic-RAG functionality with Vectara",
|
125 |
)
|
126 |
)
|
127 |
+
)
|
128 |
+
|
129 |
+
if collapsed:
|
130 |
+
return expanded_footer_ref.current
|
131 |
+
else:
|
132 |
+
return collapsed_footer_ref.current
|
133 |
+
|
134 |
+
|
135 |
+
|
136 |
+
|
137 |
+
# from reactpy import component, html, svg, hooks
|
138 |
+
|
139 |
+
# @component
|
140 |
+
# def Footer(collapsed, set_collapsed):
|
141 |
+
|
142 |
+
# if collapsed:
|
143 |
+
# return html.footer(
|
144 |
+
# {
|
145 |
+
# "style": {
|
146 |
+
# "backgroundColor": "#FFFFFF",
|
147 |
+
# "position": "fixed",
|
148 |
+
# "bottom": 0,
|
149 |
+
# "width": "100%",
|
150 |
+
# "height": "50px",
|
151 |
+
# }
|
152 |
+
# },
|
153 |
+
# html.button(
|
154 |
+
# {
|
155 |
+
# "style": {
|
156 |
+
# "background": "none",
|
157 |
+
# "border": "none",
|
158 |
+
# "color": "#757575",
|
159 |
+
# "cursor": "pointer",
|
160 |
+
# "position": "absolute",
|
161 |
+
# "bottom": "5px",
|
162 |
+
# "right": "10px",
|
163 |
+
# },
|
164 |
+
# "type": "button",
|
165 |
+
# "on_click": lambda _: set_collapsed(False)
|
166 |
+
# },
|
167 |
+
# svg.svg(
|
168 |
+
# {
|
169 |
+
# "xmlns": "http://www.w3.org/2000/svg",
|
170 |
+
# "width": "24",
|
171 |
+
# "height": "24",
|
172 |
+
# "fill": "none",
|
173 |
+
# "stroke": "currentColor",
|
174 |
+
# "stroke-linecap": "round",
|
175 |
+
# "stroke-linejoin": "round",
|
176 |
+
# "stroke-width": "3",
|
177 |
+
# "viewBox": "0 0 24 24",
|
178 |
+
# },
|
179 |
+
# svg.path({"d": "M19 14l-7-7-7 7"})
|
180 |
+
# )
|
181 |
+
# )
|
182 |
+
# )
|
183 |
+
# else:
|
184 |
+
# return html.footer(
|
185 |
+
# {
|
186 |
+
# "style": {
|
187 |
+
# "backgroundColor": "#FFFFFF",
|
188 |
+
# "position": "fixed",
|
189 |
+
# "bottom": 0,
|
190 |
+
# "width": "100%",
|
191 |
+
# }
|
192 |
+
# },
|
193 |
+
# html.div(
|
194 |
+
# {
|
195 |
+
# "style": {
|
196 |
+
# "backgroundColor": "#FFFFFF",
|
197 |
+
# "padding": "0px 20px 0px 50px",
|
198 |
+
# "position": "relative",
|
199 |
+
# "display": "block",
|
200 |
+
# }
|
201 |
+
# },
|
202 |
+
# html.button(
|
203 |
+
# {
|
204 |
+
# "style": {
|
205 |
+
# "position": "absolute",
|
206 |
+
# "right": "10px",
|
207 |
+
# "background": "none",
|
208 |
+
# "border": "none",
|
209 |
+
# "color": "#757575",
|
210 |
+
# "cursor": "pointer",
|
211 |
+
# },
|
212 |
+
# "type": "button",
|
213 |
+
# "on_click": lambda _: set_collapsed(True)
|
214 |
+
# },
|
215 |
+
# svg.svg(
|
216 |
+
# {
|
217 |
+
# "xmlns": "http://www.w3.org/2000/svg",
|
218 |
+
# "width": "24",
|
219 |
+
# "height": "24",
|
220 |
+
# "fill": "none",
|
221 |
+
# "stroke": "currentColor",
|
222 |
+
# "stroke-linecap": "round",
|
223 |
+
# "stroke-linejoin": "round",
|
224 |
+
# "stroke-width": "3",
|
225 |
+
# "viewBox": "0 0 24 24",
|
226 |
+
# },
|
227 |
+
# svg.path({"d": "M18 6L6 18"}),
|
228 |
+
# svg.path({"d": "M6 6l12 12"})
|
229 |
+
# )
|
230 |
+
# ),
|
231 |
+
# html.p(
|
232 |
+
# {
|
233 |
+
# "style": {
|
234 |
+
# "fontSize": "20px",
|
235 |
+
# "color": "#4b4851"
|
236 |
+
# }
|
237 |
+
# },
|
238 |
+
# "How this works?",
|
239 |
+
# ),
|
240 |
+
# html.p(
|
241 |
+
# {
|
242 |
+
# "style": {
|
243 |
+
# "color": "#757575",
|
244 |
+
# }
|
245 |
+
# },
|
246 |
+
# "This app was built with ",
|
247 |
+
# html.a(
|
248 |
+
# {
|
249 |
+
# "href": "https://vectara.com/",
|
250 |
+
# "target": "_blank",
|
251 |
+
# },
|
252 |
+
# "Vectara",
|
253 |
+
# ),
|
254 |
+
# html.br(),
|
255 |
+
# "It demonstrates the use of Agentic-RAG functionality with Vectara",
|
256 |
+
# )
|
257 |
+
# )
|
258 |
+
# )
|
header.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
from reactpy import component, html, svg, hooks
|
|
|
2 |
|
3 |
@component
|
4 |
def Header(demo_name: str, short_description: str, extra_info: str, start_over):
|
@@ -7,16 +8,11 @@ def Header(demo_name: str, short_description: str, extra_info: str, start_over):
|
|
7 |
def toggle_header(event=None):
|
8 |
set_more_info(not more_info)
|
9 |
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
"justifyContent": "space-between",
|
16 |
-
"alignItems": "center",
|
17 |
-
}
|
18 |
-
},
|
19 |
-
html.div(
|
20 |
{
|
21 |
"style": {
|
22 |
"display": "flex",
|
@@ -46,7 +42,46 @@ def Header(demo_name: str, short_description: str, extra_info: str, start_over):
|
|
46 |
},
|
47 |
f"{demo_name}"
|
48 |
),
|
49 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
html.div(
|
51 |
{
|
52 |
"style": {
|
@@ -123,30 +158,5 @@ def Header(demo_name: str, short_description: str, extra_info: str, start_over):
|
|
123 |
)
|
124 |
)
|
125 |
),
|
126 |
-
|
127 |
-
{
|
128 |
-
"style": {
|
129 |
-
"flex": 2,
|
130 |
-
"textAlign": "right",
|
131 |
-
"padding": "10px",
|
132 |
-
}
|
133 |
-
},
|
134 |
-
html.button(
|
135 |
-
{
|
136 |
-
"style": {
|
137 |
-
"backgroundColor": "#FFFFFF",
|
138 |
-
"color": "#757575",
|
139 |
-
"fontSize": "14px",
|
140 |
-
"cursor": "pointer",
|
141 |
-
"border": "1px solid #e2dfdf",
|
142 |
-
"borderRadius": "5px",
|
143 |
-
"padding": "6px 20px",
|
144 |
-
"marginRight": "15px",
|
145 |
-
},
|
146 |
-
"type": "button",
|
147 |
-
"onClick": start_over,
|
148 |
-
},
|
149 |
-
"Start Over?"
|
150 |
-
)
|
151 |
-
)
|
152 |
)
|
|
|
1 |
from reactpy import component, html, svg, hooks
|
2 |
+
from reactpy.core.hooks import use_ref
|
3 |
|
4 |
@component
|
5 |
def Header(demo_name: str, short_description: str, extra_info: str, start_over):
|
|
|
8 |
def toggle_header(event=None):
|
9 |
set_more_info(not more_info)
|
10 |
|
11 |
+
logo_section_ref = use_ref(None)
|
12 |
+
start_over_ref = use_ref(None)
|
13 |
+
|
14 |
+
if logo_section_ref.current is None:
|
15 |
+
logo_section_ref.current = html.div(
|
|
|
|
|
|
|
|
|
|
|
16 |
{
|
17 |
"style": {
|
18 |
"display": "flex",
|
|
|
42 |
},
|
43 |
f"{demo_name}"
|
44 |
),
|
45 |
+
)
|
46 |
+
|
47 |
+
if start_over_ref.current is None:
|
48 |
+
start_over_ref.current = html.div(
|
49 |
+
{
|
50 |
+
"style": {
|
51 |
+
"flex": 2,
|
52 |
+
"textAlign": "right",
|
53 |
+
"padding": "10px",
|
54 |
+
}
|
55 |
+
},
|
56 |
+
html.button(
|
57 |
+
{
|
58 |
+
"style": {
|
59 |
+
"backgroundColor": "#FFFFFF",
|
60 |
+
"color": "#757575",
|
61 |
+
"fontSize": "14px",
|
62 |
+
"cursor": "pointer",
|
63 |
+
"border": "1px solid #e2dfdf",
|
64 |
+
"borderRadius": "5px",
|
65 |
+
"padding": "6px 20px",
|
66 |
+
"marginRight": "15px",
|
67 |
+
},
|
68 |
+
"type": "button",
|
69 |
+
"onClick": start_over,
|
70 |
+
},
|
71 |
+
"Start Over?"
|
72 |
+
)
|
73 |
+
)
|
74 |
+
|
75 |
+
return html.header(
|
76 |
+
{
|
77 |
+
"style": {
|
78 |
+
"backgroundColor": "#FFFFFF",
|
79 |
+
"display": "flex",
|
80 |
+
"justifyContent": "space-between",
|
81 |
+
"alignItems": "center",
|
82 |
+
}
|
83 |
+
},
|
84 |
+
logo_section_ref.current,
|
85 |
html.div(
|
86 |
{
|
87 |
"style": {
|
|
|
158 |
)
|
159 |
)
|
160 |
),
|
161 |
+
start_over_ref.current
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
)
|