WeMWish commited on
Commit
c349300
·
1 Parent(s): 557ed35

Replace literature toggle with 4-button consultation system

Browse files

- Remove external literature toggle button from chat UI
- Add contextual 4-button literature consultation system that appears after agent responses
- Skip consultation buttons for first user query, show on subsequent queries
- Implement 4 consultation options: underlying paper, external literature, both sources, skip
- Add proper styling with color-coded buttons in 2x2 grid layout
- Generate synthetic user queries based on button selection
- Maintain compatibility with existing R server literature handling

Files changed (3) hide show
  1. chat_ui.R +64 -72
  2. www/chat_script.js +127 -20
  3. www/chat_styles.css +75 -15
chat_ui.R CHANGED
@@ -1,73 +1,65 @@
1
- # chat_ui.R
2
-
3
- library(shiny)
4
-
5
- # Function to create the chat button UI
6
- chatButtonUI <- function() {
7
- actionButton("toggleChatBtn", "Chat", icon = icon("comments"),
8
- class = "btn-primary chat-toggle-button") # Added a class for styling
9
- }
10
-
11
- # Function to create the chat sidebar UI
12
- chatSidebarUI <- function() {
13
- sidebar_id_to_use <- "chatSidebar"
14
- print(paste("--- In chat_ui.R, chatSidebarUI IS DEFINING ID AS:", sidebar_id_to_use, "---")) # New print
15
-
16
- # Source the warning overlay code
17
- source("warning_overlay.R", local = TRUE)
18
-
19
- tagList(
20
- # Initialize shinyjs (used for disabling inputs and potentially other UI manipulations)
21
- shinyjs::useShinyjs(),
22
-
23
- # The old warningOverlayUI() and its specific JS are removed as we shift to chat messages.
24
- # tags$script(HTML(warningOverlayJS)), # This JS was for the old overlay
25
-
26
- absolutePanel(
27
- id = sidebar_id_to_use, # Use the variable here
28
- class = "chat-sidebar", # Class for styling
29
- top = 0, right = 0, width = "350px", height = "100%", # Initial position and size
30
- draggable = FALSE,
31
- fixed = TRUE, # Make it fixed position
32
- style = "display: none; background-color: #f8f9fa; border-left: 1px solid #dee2e6; padding: 15px; box-shadow: -2px 0 5px rgba(0,0,0,0.1); z-index: 1050; position: fixed; right: 0; transition: width 0.1s ease-out; min-width: 250px; max-width: 800px;", # Ensure right overlay
33
-
34
- # Resize handle on the left edge
35
- div(
36
- class = "resize-handle",
37
- style = "position: absolute; left: 0; top: 0; width: 5px; height: 100%; cursor: ew-resize; background-color: transparent; z-index: 1060;"
38
- ),
39
-
40
- h4("TaijiChat Assistant"),
41
- hr(),
42
- div(
43
- id = "chatMessages",
44
- class = "chat-messages-area", # For styling the message display
45
- style = "height: calc(100vh - 200px); overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; background-color: white;"
46
- # Placeholder for messages
47
- ),
48
- div(
49
- class = "literature-toggle-container",
50
- style = "margin: 5px 0;",
51
- actionButton("literatureToggleBtn",
52
- HTML('<i class="fa fa-search"></i> External Literature'),
53
- class = "btn btn-outline-info literature-toggle-btn",
54
- style = "width: 100%; font-size: 12px;")
55
- ),
56
- div(
57
- class = "chat-input-area", # For styling input area
58
- style = "display: flex; align-items: stretch;",
59
- textInput("chatInput", NULL, placeholder = "Ask something...", width = "calc(100% - 80px)"),
60
- actionButton("sendChatMsg", "Send", icon = icon("paper-plane"), class = "btn-success", style = "margin-left: 5px;")
61
- ),
62
- # Close button for the sidebar
63
- tags$button(
64
- id = "closeChatSidebarBtn",
65
- type = "button",
66
- class = "close", # Standard Bootstrap close button
67
- `aria-label` = "Close",
68
- style = "position: absolute; top: 10px; right: 15px; font-size: 1.5rem; color: #000; opacity: 0.5; background: transparent; border: 0;",
69
- tags$span(`aria-hidden` = "true", HTML("&times;"))
70
- )
71
- )
72
- )
73
  }
 
1
+ # chat_ui.R
2
+
3
+ library(shiny)
4
+
5
+ # Function to create the chat button UI
6
+ chatButtonUI <- function() {
7
+ actionButton("toggleChatBtn", "Chat", icon = icon("comments"),
8
+ class = "btn-primary chat-toggle-button") # Added a class for styling
9
+ }
10
+
11
+ # Function to create the chat sidebar UI
12
+ chatSidebarUI <- function() {
13
+ sidebar_id_to_use <- "chatSidebar"
14
+ print(paste("--- In chat_ui.R, chatSidebarUI IS DEFINING ID AS:", sidebar_id_to_use, "---")) # New print
15
+
16
+ # Source the warning overlay code
17
+ source("warning_overlay.R", local = TRUE)
18
+
19
+ tagList(
20
+ # Initialize shinyjs (used for disabling inputs and potentially other UI manipulations)
21
+ shinyjs::useShinyjs(),
22
+
23
+ # The old warningOverlayUI() and its specific JS are removed as we shift to chat messages.
24
+ # tags$script(HTML(warningOverlayJS)), # This JS was for the old overlay
25
+
26
+ absolutePanel(
27
+ id = sidebar_id_to_use, # Use the variable here
28
+ class = "chat-sidebar", # Class for styling
29
+ top = 0, right = 0, width = "350px", height = "100%", # Initial position and size
30
+ draggable = FALSE,
31
+ fixed = TRUE, # Make it fixed position
32
+ style = "display: none; background-color: #f8f9fa; border-left: 1px solid #dee2e6; padding: 15px; box-shadow: -2px 0 5px rgba(0,0,0,0.1); z-index: 1050; position: fixed; right: 0; transition: width 0.1s ease-out; min-width: 250px; max-width: 800px;", # Ensure right overlay
33
+
34
+ # Resize handle on the left edge
35
+ div(
36
+ class = "resize-handle",
37
+ style = "position: absolute; left: 0; top: 0; width: 5px; height: 100%; cursor: ew-resize; background-color: transparent; z-index: 1060;"
38
+ ),
39
+
40
+ h4("TaijiChat Assistant"),
41
+ hr(),
42
+ div(
43
+ id = "chatMessages",
44
+ class = "chat-messages-area", # For styling the message display
45
+ style = "height: calc(100vh - 200px); overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; background-color: white;"
46
+ # Placeholder for messages
47
+ ),
48
+ div(
49
+ class = "chat-input-area", # For styling input area
50
+ style = "display: flex; align-items: stretch;",
51
+ textInput("chatInput", NULL, placeholder = "Ask something...", width = "calc(100% - 80px)"),
52
+ actionButton("sendChatMsg", "Send", icon = icon("paper-plane"), class = "btn-success", style = "margin-left: 5px;")
53
+ ),
54
+ # Close button for the sidebar
55
+ tags$button(
56
+ id = "closeChatSidebarBtn",
57
+ type = "button",
58
+ class = "close", # Standard Bootstrap close button
59
+ `aria-label` = "Close",
60
+ style = "position: absolute; top: 10px; right: 15px; font-size: 1.5rem; color: #000; opacity: 0.5; background: transparent; border: 0;",
61
+ tags$span(`aria-hidden` = "true", HTML("&times;"))
62
+ )
63
+ )
64
+ )
 
 
 
 
 
 
 
 
65
  }
www/chat_script.js CHANGED
@@ -112,8 +112,64 @@ window.showFullImage = function(imagePath) {
112
  $('#fullImageModal').show();
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  function initializeChatUI() {
116
  var isFirstChatOpenThisSession = true;
 
117
  var isResizing = false;
118
  var startX;
119
  var startWidth;
@@ -306,6 +362,10 @@ function initializeChatUI() {
306
  var $chatMessages = $('#chatMessages');
307
 
308
  var $messageDiv = $('<div></div>').addClass('chat-message').addClass(messageClass);
 
 
 
 
309
 
310
  if (messageType === 'user') {
311
  // For user messages, just append the text directly without animation
@@ -378,6 +438,17 @@ function initializeChatUI() {
378
  }
379
  $messageDiv.html(messageText);
380
  $chatMessages.append($messageDiv);
 
 
 
 
 
 
 
 
 
 
 
381
  if (autoScrollEnabled) {
382
  $chatMessages.scrollTop($chatMessages[0].scrollHeight);
383
  }
@@ -386,6 +457,16 @@ function initializeChatUI() {
386
  $chatMessages.append($messageDiv);
387
  var lines = messageText.split('\n');
388
  typeTextLines($messageDiv, lines, '', 5, function() {
 
 
 
 
 
 
 
 
 
 
389
  if (autoScrollEnabled) {
390
  $chatMessages.scrollTop($chatMessages[0].scrollHeight);
391
  }
@@ -402,6 +483,52 @@ function initializeChatUI() {
402
  }
403
  }
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  // Thought toggle handler
406
  $(document).off('click.thoughtToggle').on('click.thoughtToggle', '.thought-toggle-arrow', function() {
407
  var $arrow = $(this);
@@ -536,24 +663,4 @@ function initializeChatUI() {
536
  });
537
 
538
 
539
- // Literature toggle handler
540
- $(document).off('click.literatureToggle').on('click.literatureToggle', '#literatureToggleBtn', function() {
541
- var $btn = $(this);
542
- $btn.toggleClass('active');
543
-
544
- var isEnabled = $btn.hasClass('active');
545
- Shiny.setInputValue("literature_search_enabled", isEnabled, {priority: "event"});
546
-
547
- // Update button text/icon based on state
548
- if (isEnabled) {
549
- $btn.html('<i class="fa fa-search"></i> External Literature (ON)');
550
- } else {
551
- $btn.html('<i class="fa fa-search"></i> External Literature (OFF)');
552
- }
553
- });
554
-
555
- // Initialize button state (default: disabled)
556
- setTimeout(function() {
557
- Shiny.setInputValue("literature_search_enabled", false);
558
- }, 100);
559
  }
 
112
  $('#fullImageModal').show();
113
  }
114
 
115
+ // Global function to add literature consultation buttons
116
+ window.addLiteratureConsultationButtons = function() {
117
+ console.log("Adding literature consultation buttons");
118
+
119
+ var $chatMessages = $('#chatMessages');
120
+ if (!$chatMessages.length) {
121
+ console.error("Chat messages container not found");
122
+ return;
123
+ }
124
+
125
+ // Add consultation message
126
+ var $consultationMsg = $('<div></div>').addClass('chat-message agent-message consultation-message');
127
+ $consultationMsg.text("Would you like to consult the underlying paper this website is based on, search external literature, try both sources, or skip additional research?");
128
+ $chatMessages.append($consultationMsg);
129
+
130
+ // Add button container
131
+ var $buttonContainer = $('<div></div>').addClass('literature-consultation-buttons');
132
+
133
+ // Create the 4 buttons
134
+ var $btnUnderlying = $('<button></button>')
135
+ .addClass('consultation-btn btn-underlying')
136
+ .text('Consult Underlying Paper')
137
+ .data('query-type', 'underlying');
138
+
139
+ var $btnExternal = $('<button></button>')
140
+ .addClass('consultation-btn btn-external')
141
+ .text('Search External Literature')
142
+ .data('query-type', 'external');
143
+
144
+ var $btnBoth = $('<button></button>')
145
+ .addClass('consultation-btn btn-both')
146
+ .text('Try Both Sources')
147
+ .data('query-type', 'both');
148
+
149
+ var $btnSkip = $('<button></button>')
150
+ .addClass('consultation-btn btn-skip')
151
+ .text('Skip Additional Research')
152
+ .data('query-type', 'skip');
153
+
154
+ // Add buttons to container in 2x2 grid
155
+ var $row1 = $('<div></div>').addClass('consultation-row');
156
+ var $row2 = $('<div></div>').addClass('consultation-row');
157
+
158
+ $row1.append($btnUnderlying).append($btnExternal);
159
+ $row2.append($btnBoth).append($btnSkip);
160
+
161
+ $buttonContainer.append($row1).append($row2);
162
+ $chatMessages.append($buttonContainer);
163
+
164
+ // Scroll to bottom
165
+ $chatMessages.scrollTop($chatMessages[0].scrollHeight);
166
+
167
+ console.log("Literature consultation buttons added successfully");
168
+ }
169
+
170
  function initializeChatUI() {
171
  var isFirstChatOpenThisSession = true;
172
+ var isFirstUserQuery = true; // Track whether user has made their first actual query
173
  var isResizing = false;
174
  var startX;
175
  var startWidth;
 
362
  var $chatMessages = $('#chatMessages');
363
 
364
  var $messageDiv = $('<div></div>').addClass('chat-message').addClass(messageClass);
365
+
366
+ // Show consultation buttons after every non-thinking, non-disclaimer agent response, except for the first user query
367
+ var shouldShowConsultation = (messageType === 'agent' && !isThinkingMessage && !isDisclaimer && !isFirstUserQuery);
368
+ console.log("Message processing:", {messageType, isThinkingMessage, isDisclaimer, isFirstUserQuery, shouldShowConsultation});
369
 
370
  if (messageType === 'user') {
371
  // For user messages, just append the text directly without animation
 
438
  }
439
  $messageDiv.html(messageText);
440
  $chatMessages.append($messageDiv);
441
+
442
+ // Reset first user query flag after first agent response
443
+ if (isFirstUserQuery) {
444
+ console.log("First user query completed, enabling consultation buttons for future queries");
445
+ isFirstUserQuery = false;
446
+ }
447
+
448
+ if (shouldShowConsultation) {
449
+ console.log("Triggering consultation buttons for HTML message");
450
+ window.addLiteratureConsultationButtons();
451
+ }
452
  if (autoScrollEnabled) {
453
  $chatMessages.scrollTop($chatMessages[0].scrollHeight);
454
  }
 
457
  $chatMessages.append($messageDiv);
458
  var lines = messageText.split('\n');
459
  typeTextLines($messageDiv, lines, '', 5, function() {
460
+ // Reset first user query flag after first agent response
461
+ if (isFirstUserQuery) {
462
+ console.log("First user query completed, enabling consultation buttons for future queries");
463
+ isFirstUserQuery = false;
464
+ }
465
+
466
+ if (shouldShowConsultation) {
467
+ console.log("Triggering consultation buttons for text message");
468
+ window.addLiteratureConsultationButtons();
469
+ }
470
  if (autoScrollEnabled) {
471
  $chatMessages.scrollTop($chatMessages[0].scrollHeight);
472
  }
 
483
  }
484
  }
485
 
486
+
487
+ // Literature consultation button handler
488
+ $(document).off('click.consultationBtn').on('click.consultationBtn', '.consultation-btn', function() {
489
+ console.log("Consultation button clicked");
490
+ var $btn = $(this);
491
+ var queryType = $btn.data('query-type');
492
+ var queryText = '';
493
+ console.log("Button query type:", queryType);
494
+
495
+ // Generate synthetic user query based on button selection
496
+ switch(queryType) {
497
+ case 'underlying':
498
+ queryText = 'Please provide more details from the underlying research paper that supports your previous response.';
499
+ break;
500
+ case 'external':
501
+ queryText = 'Please search external literature to provide additional context and validation for your previous response.';
502
+ break;
503
+ case 'both':
504
+ queryText = 'Please provide both details from the underlying paper and search external literature to give comprehensive context for your previous response.';
505
+ break;
506
+ case 'skip':
507
+ queryText = 'Thank you, no additional research needed.';
508
+ break;
509
+ }
510
+
511
+ // Remove all consultation elements
512
+ $('.consultation-message').remove();
513
+ $('.literature-consultation-buttons').remove();
514
+
515
+ // Add synthetic user message and trigger processing
516
+ if (queryType !== 'skip') {
517
+ addChatMessage(queryText, 'user');
518
+
519
+ // Set literature preference based on button selection
520
+ var literatureEnabled = (queryType === 'external' || queryType === 'both');
521
+ Shiny.setInputValue("literature_search_enabled", literatureEnabled, {priority: "event"});
522
+
523
+ // Send the query
524
+ Shiny.setInputValue("user_chat_message", queryText, {priority: "event"});
525
+
526
+ // Disable input during processing
527
+ $('#chatInput').prop('disabled', true);
528
+ $('#sendChatMsg').prop('disabled', true);
529
+ }
530
+ });
531
+
532
  // Thought toggle handler
533
  $(document).off('click.thoughtToggle').on('click.thoughtToggle', '.thought-toggle-arrow', function() {
534
  var $arrow = $(this);
 
663
  });
664
 
665
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
666
  }
www/chat_styles.css CHANGED
@@ -169,29 +169,89 @@
169
  user-select: none;
170
  }
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
- /* Literature toggle button styles */
174
- .literature-toggle-btn {
 
 
 
 
 
 
175
  transition: all 0.3s ease;
176
- border: 2px solid #17a2b8;
 
 
 
 
177
  }
178
 
179
- .literature-toggle-btn.active {
180
- background-color: #17a2b8 !important;
181
- color: white !important;
182
- border-color: #17a2b8;
183
  }
184
 
185
- .literature-toggle-btn:not(.active) {
186
- background-color: transparent;
187
- color: #17a2b8;
188
  }
189
 
190
- .literature-toggle-btn:hover {
191
- background-color: #17a2b8;
192
  color: white;
193
  }
194
 
195
- .literature-toggle-container {
196
- margin: 5px 0;
197
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  user-select: none;
170
  }
171
 
172
+ /* Literature consultation styles */
173
+ .consultation-message {
174
+ background-color: #f0f8ff !important;
175
+ border: 1px solid #87ceeb;
176
+ color: #2f4f4f;
177
+ font-style: italic;
178
+ margin-bottom: 5px !important;
179
+ }
180
+
181
+ .literature-consultation-buttons {
182
+ margin: 10px 0;
183
+ padding: 10px;
184
+ background-color: #f9f9f9;
185
+ border-radius: 10px;
186
+ border: 1px solid #e0e0e0;
187
+ clear: both;
188
+ }
189
+
190
+ .consultation-row {
191
+ display: flex;
192
+ gap: 10px;
193
+ margin-bottom: 10px;
194
+ }
195
+
196
+ .consultation-row:last-child {
197
+ margin-bottom: 0;
198
+ }
199
 
200
+ .consultation-btn {
201
+ flex: 1;
202
+ padding: 10px 15px;
203
+ border: none;
204
+ border-radius: 8px;
205
+ font-size: 14px;
206
+ font-weight: 500;
207
+ cursor: pointer;
208
  transition: all 0.3s ease;
209
+ text-align: center;
210
+ min-height: 45px;
211
+ display: flex;
212
+ align-items: center;
213
+ justify-content: center;
214
  }
215
 
216
+ .btn-underlying {
217
+ background-color: #28a745;
218
+ color: white;
 
219
  }
220
 
221
+ .btn-underlying:hover {
222
+ background-color: #218838;
223
+ transform: translateY(-2px);
224
  }
225
 
226
+ .btn-external {
227
+ background-color: #007bff;
228
  color: white;
229
  }
230
 
231
+ .btn-external:hover {
232
+ background-color: #0056b3;
233
+ transform: translateY(-2px);
234
+ }
235
+
236
+ .btn-both {
237
+ background-color: #ffc107;
238
+ color: #212529;
239
+ }
240
+
241
+ .btn-both:hover {
242
+ background-color: #e0a800;
243
+ transform: translateY(-2px);
244
+ }
245
+
246
+ .btn-skip {
247
+ background-color: #6c757d;
248
+ color: white;
249
+ }
250
+
251
+ .btn-skip:hover {
252
+ background-color: #545b62;
253
+ transform: translateY(-2px);
254
+ }
255
+
256
+
257
+