Spaces:
Paused
Paused
| // components/feedback-component.js - Message feedback functionality | |
| import { StateManager } from '../services/state-manager.js'; | |
| import { ApiService } from '../services/api-service.js'; | |
| import { TranslationService } from '../services/translation-service.js'; | |
| import { Utils } from '../utils.js'; | |
| export const FeedbackComponent = { | |
| elements: { | |
| feedbackOverlay: null, | |
| closeFeedbackBtn: null, | |
| cancelFeedbackBtn: null, | |
| submitFeedbackBtn: null, | |
| feedbackInput: null, | |
| feedbackRatingDisplay: null, | |
| feedbackMessagePreview: null | |
| }, | |
| currentFeedback: { | |
| messageIndex: null, | |
| modelType: null, | |
| rating: null, // 'like', 'dislike', 'mixed' | |
| messageContent: null | |
| }, | |
| /** | |
| * Initialize the feedback component | |
| */ | |
| init() { | |
| // Get DOM elements | |
| this.elements.feedbackOverlay = document.getElementById('feedback-overlay'); | |
| this.elements.closeFeedbackBtn = document.getElementById('closeFeedbackBtn'); | |
| this.elements.cancelFeedbackBtn = document.getElementById('cancelFeedbackBtn'); | |
| this.elements.submitFeedbackBtn = document.getElementById('submitFeedbackBtn'); | |
| this.elements.feedbackInput = document.getElementById('feedbackInput'); | |
| this.elements.feedbackRatingDisplay = document.getElementById('feedbackRatingDisplay'); | |
| this.elements.feedbackMessagePreview = document.getElementById('feedbackMessagePreview'); | |
| this.attachOutsideClickListener(); | |
| this.attachEventListeners(); | |
| }, | |
| attachOutsideClickListener() { | |
| this.elements.feedbackOverlay.addEventListener('click', (e) => { | |
| // Check if click is on the overlay itself (not its children) | |
| if (e.target === this.elements.feedbackOverlay) { | |
| this.closeModal(); | |
| } | |
| }); | |
| }, | |
| /** | |
| * Attach event listeners | |
| */ | |
| attachEventListeners() { | |
| this.elements.closeFeedbackBtn.addEventListener('click', () => this.closeModal()); | |
| this.elements.cancelFeedbackBtn.addEventListener('click', () => this.closeModal()); | |
| this.elements.submitFeedbackBtn.addEventListener('click', () => this.submitFeedback()); | |
| // Enter to submit (optional comment) | |
| this.elements.feedbackInput.addEventListener('keydown', (e) => { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| this.submitFeedback(); | |
| } | |
| }); | |
| }, | |
| /** | |
| * Open feedback modal | |
| * @param {number} messageIndex - Index of the message | |
| * @param {string} modelType - Type of model | |
| * @param {string} rating - 'like', 'dislike', or 'mixed' | |
| * @param {string} messageContent - Content of the message being rated | |
| */ | |
| openModal(messageIndex, modelType, rating, messageContent) { | |
| this.currentFeedback = { | |
| messageIndex, | |
| modelType, | |
| rating, | |
| messageContent | |
| }; | |
| // Update modal content | |
| this.updateModalContent(rating, messageContent); | |
| // Show modal | |
| this.elements.feedbackOverlay.style.display = ''; | |
| // Focus on textarea | |
| setTimeout(() => this.elements.feedbackInput.focus(), 100); | |
| }, | |
| /** | |
| * Update modal content based on rating | |
| * @param {string} rating - The rating type | |
| * @param {string} messageContent - The message content | |
| */ | |
| updateModalContent(rating, messageContent) { | |
| // Update rating display | |
| const ratingEmoji = { | |
| 'like': '👍', | |
| 'dislike': '👎', | |
| 'mixed': '~' | |
| }; | |
| const ratingText = { | |
| 'like': 'feedback_like_title', | |
| 'dislike': 'feedback_dislike_title', | |
| 'mixed': 'feedback_neutral_title' | |
| }; | |
| this.elements.feedbackRatingDisplay.textContent = ratingEmoji[rating] + ' '; | |
| this.elements.feedbackRatingDisplay.dataset.i18n = ratingText[rating]; | |
| // Update message preview (truncate if too long) | |
| const preview = messageContent.length > 150 | |
| ? messageContent.substring(0, 150) + '...' | |
| : messageContent; | |
| this.elements.feedbackMessagePreview.textContent = preview; | |
| // Clear previous comment | |
| this.elements.feedbackInput.value = ''; | |
| // Apply translations | |
| TranslationService.applyTranslation(); | |
| }, | |
| /** | |
| * Close the feedback modal | |
| */ | |
| closeModal() { | |
| this.elements.feedbackOverlay.style.display = 'none'; | |
| this.currentFeedback = { | |
| messageIndex: null, | |
| modelType: null, | |
| rating: null, | |
| messageContent: null | |
| }; | |
| }, | |
| /** | |
| * Submit feedback to the server | |
| */ | |
| async submitFeedback() { | |
| const comment = this.elements.feedbackInput.value.trim(); | |
| const feedbackData = { | |
| message_index: this.currentFeedback.messageIndex, | |
| model_type: this.currentFeedback.modelType, | |
| rating: this.currentFeedback.rating, | |
| comment: comment || "", // Optional | |
| reply_content: this.currentFeedback.messageContent, | |
| user_id: Utils.getMachineId(), | |
| session_id: StateManager.sessionId, | |
| conversation_id: StateManager.getConversationId(this.currentFeedback.modelType) | |
| }; | |
| try { | |
| const result = await ApiService.submitFeedback(feedbackData); | |
| if (result.success) { | |
| showSnackbar(translations[StateManager.currentLang]["feedback_submitted"], 'success'); | |
| // Mark message as rated in state (optional - for UI indication) | |
| this.markMessageAsRated( | |
| this.currentFeedback.modelType, | |
| this.currentFeedback.messageIndex, | |
| this.currentFeedback.rating | |
| ); | |
| this.closeModal(); | |
| } else { | |
| showSnackbar(translations[StateManager.currentLang]["feedback_failed_server_error"], 'error'); | |
| } | |
| } catch (err) { | |
| showSnackbar(translations[StateManager.currentLang]["feedback_failed_network_error"], 'error'); | |
| } | |
| }, | |
| /** | |
| * Mark a message as rated (for UI purposes) | |
| * @param {string} modelType - Model type | |
| * @param {number} messageIndex - Message index | |
| * @param {string} rating - Rating given | |
| */ | |
| markMessageAsRated(modelType, messageIndex, rating) { | |
| const messages = StateManager.getMessages(modelType); | |
| if (messages[messageIndex]) { | |
| messages[messageIndex].feedback = { | |
| rated: true, | |
| rating: rating | |
| }; | |
| window.dispatchEvent(new CustomEvent('feedbackSubmitted', { | |
| detail: { modelType, messageIndex, rating } | |
| })); | |
| } | |
| } | |
| }; |