From 32501e4a0f22cc60da3ca8310c45878914c5dae3 Mon Sep 17 00:00:00 2001 From: dal Date: Mon, 28 Apr 2025 14:00:36 -0600 Subject: [PATCH 1/2] raindrop added --- api/Cargo.toml | 1 + api/libs/agents/Cargo.toml | 2 +- api/libs/agents/src/agent.rs | 70 +++++++++++++++++++- api/libs/raindrop/Cargo.toml | 22 ++++++ api/libs/raindrop/src/errors.rs | 27 ++++++++ api/libs/raindrop/src/lib.rs | 114 ++++++++++++++++++++++++++++++++ api/libs/raindrop/src/types.rs | 67 +++++++++++++++++++ 7 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 api/libs/raindrop/Cargo.toml create mode 100644 api/libs/raindrop/src/errors.rs create mode 100644 api/libs/raindrop/src/lib.rs create mode 100644 api/libs/raindrop/src/types.rs diff --git a/api/Cargo.toml b/api/Cargo.toml index 3593b0f12..ade8090c2 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -12,6 +12,7 @@ members = [ "libs/dataset_security", "libs/email", "libs/stored_values", + "libs/raindrop", ] resolver = "2" diff --git a/api/libs/agents/Cargo.toml b/api/libs/agents/Cargo.toml index 37a8e7e76..3474724ba 100644 --- a/api/libs/agents/Cargo.toml +++ b/api/libs/agents/Cargo.toml @@ -34,7 +34,7 @@ sqlx = { workspace = true } stored_values = { path = "../stored_values" } tokio-retry = { workspace = true } thiserror = { workspace = true } - +raindrop = { path = "../raindrop" } # Development dependencies [dev-dependencies] tokio-test = { workspace = true } diff --git a/api/libs/agents/src/agent.rs b/api/libs/agents/src/agent.rs index 053834de0..471fa1057 100644 --- a/api/libs/agents/src/agent.rs +++ b/api/libs/agents/src/agent.rs @@ -11,9 +11,13 @@ use std::time::{Duration, Instant}; use std::{collections::HashMap, env, sync::Arc}; use tokio::sync::{broadcast, mpsc, RwLock}; use tokio_retry::{strategy::ExponentialBackoff, Retry}; -use tracing::{error, warn}; +use tracing::{debug, error, info, instrument, warn}; use uuid::Uuid; +// Raindrop imports +use raindrop::types::{AiData as RaindropAiData, Event as RaindropEvent}; +use raindrop::RaindropClient; + // Type definition for tool registry to simplify complex type // No longer needed, defined below use crate::models::AgentThread; @@ -561,6 +565,9 @@ impl Agent { trace_builder: Option, parent_span: Option, ) -> Result<()> { + // Attempt to initialize Raindrop client (non-blocking) + let raindrop_client = RaindropClient::new().ok(); + // Set the initial thread { let mut current = agent.current_thread.write().await; @@ -721,6 +728,35 @@ impl Agent { ..Default::default() }; + // --- Track Request with Raindrop --- + if let Some(client) = raindrop_client.clone() { + let request_clone = request.clone(); // Clone request for tracking + let user_id = agent.user_id.clone(); + let session_id = agent.session_id.to_string(); + let current_history = agent.get_conversation_history().await.unwrap_or_default(); + tokio::spawn(async move { + let event = RaindropEvent { + user_id: user_id.to_string(), + event: "llm_request".to_string(), + properties: Some(HashMap::from([( + "conversation_history".to_string(), + serde_json::to_value(¤t_history).unwrap_or(Value::Null), + )])), + attachments: None, + ai_data: Some(RaindropAiData { + model: request_clone.model.clone(), + input: serde_json::to_string(&request_clone.messages).unwrap_or_default(), + output: "".to_string(), // Output is not known yet + convo_id: Some(session_id.clone()), + }), + event_id: None, // Raindrop assigns this + timestamp: Some(chrono::Utc::now()), + }; + if let Err(e) = client.track_events(vec![event]).await {} + }); + } + // --- End Track Request --- + // --- Retry Logic for Initial Stream Request --- let retry_strategy = ExponentialBackoff::from_millis(100).take(3); // Retry 3 times, ~100ms, ~200ms, ~400ms @@ -980,6 +1016,37 @@ impl Agent { // Update thread with assistant message agent.update_current_thread(final_message.clone()).await?; + // --- Track Response with Raindrop --- + if let Some(client) = raindrop_client { + let request_clone = request.clone(); // Clone again for response tracking + let final_message_clone = final_message.clone(); + let user_id = agent.user_id.clone(); + let session_id = agent.session_id.to_string(); + // Get history *after* adding the final message + let current_history = agent.get_conversation_history().await.unwrap_or_default(); + tokio::spawn(async move { + let event = RaindropEvent { + user_id: user_id.to_string(), + event: "llm_response".to_string(), + properties: Some(HashMap::from([( + "conversation_history".to_string(), + serde_json::to_value(¤t_history).unwrap_or(Value::Null), + )])), + attachments: None, + ai_data: Some(RaindropAiData { + model: request_clone.model.clone(), + input: serde_json::to_string(&request_clone.messages).unwrap_or_default(), + output: serde_json::to_string(&final_message_clone).unwrap_or_default(), + convo_id: Some(session_id.clone()), + }), + event_id: None, // Raindrop assigns this + timestamp: Some(chrono::Utc::now()), + }; + if let Err(e) = client.track_events(vec![event]).await {} + }); + } + // --- End Track Response --- + // Get the updated thread state AFTER adding the final assistant message // This will be used for the potential recursive call later. let mut updated_thread_for_recursion = agent @@ -1825,4 +1892,3 @@ mod tests { assert_eq!(agent.get_state_bool("bool_key").await, None); } } - diff --git a/api/libs/raindrop/Cargo.toml b/api/libs/raindrop/Cargo.toml new file mode 100644 index 000000000..90d2babcc --- /dev/null +++ b/api/libs/raindrop/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "raindrop" +version = "0.1.0" +edition = "2021" + +[dependencies] +# Workspace dependencies +anyhow = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +tokio = { workspace = true, features = ["full"] } +tracing = { workspace = true } +chrono = { workspace = true, features = ["serde"] } +thiserror = { workspace = true } +reqwest = { workspace = true, features = ["json", "rustls-tls"] } + +# Non-workspace dependencies (if any, prefer workspace) +dotenvy = "0.15" + +[dev-dependencies] +tokio-test = { workspace = true } +mockito = { workspace = true } \ No newline at end of file diff --git a/api/libs/raindrop/src/errors.rs b/api/libs/raindrop/src/errors.rs new file mode 100644 index 000000000..63e4c2e91 --- /dev/null +++ b/api/libs/raindrop/src/errors.rs @@ -0,0 +1,27 @@ +use thiserror::Error; +use reqwest::header::InvalidHeaderValue; + +/// Custom error types for the Raindrop SDK. +#[derive(Error, Debug)] +pub enum RaindropError { + #[error("Missing Raindrop API Write Key. Set the RAINDROP_WRITE_KEY environment variable.")] + MissingApiKey, + + #[error("Invalid header value provided: {0}")] + InvalidHeaderValue(#[from] InvalidHeaderValue), + + #[error("Failed to build HTTP client: {0}")] + HttpClientBuildError(#[from] reqwest::Error), + + #[error("HTTP request failed: {0}")] + RequestError(reqwest::Error), + + #[error("Raindrop API error: {status} - {body}")] + ApiError { + status: reqwest::StatusCode, + body: String, + }, + + #[error("Failed to serialize request body: {0}")] + SerializationError(#[from] serde_json::Error), +} \ No newline at end of file diff --git a/api/libs/raindrop/src/lib.rs b/api/libs/raindrop/src/lib.rs new file mode 100644 index 000000000..484d3abcd --- /dev/null +++ b/api/libs/raindrop/src/lib.rs @@ -0,0 +1,114 @@ +#![doc = "A Rust SDK for interacting with the Raindrop.ai API."] + +pub mod errors; +pub mod types; + +use anyhow::Context; +use reqwest::{Client, header}; +use std::env; +use tracing::{debug, error, instrument}; + +use errors::RaindropError; +use types::{Event, Signal}; + +const DEFAULT_BASE_URL: &str = "https://api.raindrop.ai/v1"; + +/// Client for interacting with the Raindrop API. +#[derive(Debug, Clone)] +pub struct RaindropClient { + client: Client, + base_url: String, + write_key: String, +} + +impl RaindropClient { + /// Creates a new RaindropClient. + /// Reads the write key from the `RAINDROP_WRITE_KEY` environment variable. + /// Uses the default Raindrop API base URL. + pub fn new() -> Result { + let write_key = env::var("RAINDROP_WRITE_KEY") + .map_err(|_| RaindropError::MissingApiKey)?; + let base_url = DEFAULT_BASE_URL.to_string(); + Self::build_client(write_key, base_url) + } + + /// Creates a new RaindropClient with a specific write key and base URL. + /// Useful for testing or custom deployments. + pub fn with_key_and_url(write_key: String, base_url: &str) -> Result { + Self::build_client(write_key, base_url.to_string()) + } + + /// Builds the underlying reqwest client. + fn build_client(write_key: String, base_url: String) -> Result { + let mut headers = header::HeaderMap::new(); + headers.insert( + header::AUTHORIZATION, + header::HeaderValue::from_str(&format!("Bearer {}", write_key)) + .map_err(RaindropError::InvalidHeaderValue)?, + ); + headers.insert( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json"), + ); + + let client = Client::builder() + .default_headers(headers) + .build() + .map_err(RaindropError::HttpClientBuildError)?; + + Ok(Self { + client, + base_url, + write_key, + }) + } + + /// Tracks a batch of events. + #[instrument(skip(self, events), fields(count = events.len()))] + pub async fn track_events(&self, events: Vec) -> Result<(), RaindropError> { + if events.is_empty() { + debug!("No events to track, skipping API call."); + return Ok(()); + } + let url = format!("{}/events/track", self.base_url); + self.post_data(&url, &events).await + } + + /// Tracks a batch of signals. + #[instrument(skip(self, signals), fields(count = signals.len()))] + pub async fn track_signals(&self, signals: Vec) -> Result<(), RaindropError> { + if signals.is_empty() { + debug!("No signals to track, skipping API call."); + return Ok(()); + } + let url = format!("{}/signals/track", self.base_url); + self.post_data(&url, &signals).await + } + + /// Helper function to POST JSON data to a specified URL. + async fn post_data( + &self, + url: &str, + data: &T, + ) -> Result<(), RaindropError> { + debug!(url = url, "Sending POST request to Raindrop"); + + let response = self + .client + .post(url) + .json(data) + .send() + .await + .map_err(RaindropError::RequestError)?; + + let status = response.status(); + if status.is_success() { + debug!(url = url, status = %status, "Raindrop API call successful"); + Ok(()) + } else { + let body = response.text().await.unwrap_or_else(|_| "Failed to read error body".to_string()); + error!(url = url, status = %status, body = body, "Raindrop API call failed"); + Err(RaindropError::ApiError { status, body }) + } + } +} \ No newline at end of file diff --git a/api/libs/raindrop/src/types.rs b/api/libs/raindrop/src/types.rs new file mode 100644 index 000000000..8e0dbc222 --- /dev/null +++ b/api/libs/raindrop/src/types.rs @@ -0,0 +1,67 @@ +use std::collections::HashMap; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +/// Represents a single event to be tracked. +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Event { + pub user_id: String, + pub event: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub properties: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub attachments: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub ai_data: Option, + + // Optional fields provided by Raindrop API + #[serde(skip_serializing_if = "Option::is_none")] + pub event_id: Option, // Returned by Raindrop, optional on send + + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp: Option>, +} + +/// Represents an attachment associated with an event. +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Attachment { + #[serde(rename = "type")] // Use `type` keyword in JSON + pub attachment_type: String, // e.g., "image", "text", "json" + pub value: String, // URL or content + + #[serde(skip_serializing_if = "Option::is_none")] + pub role: Option, // e.g., "input", "output" +} + +/// Represents AI-specific data for an event. +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct AiData { + pub model: String, + pub input: String, + pub output: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub convo_id: Option, +} + +/// Represents a single signal to be tracked. +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Signal { + pub event_id: String, // The ID of the event this signal relates to + pub signal_name: String, // e.g., "thumbs_down", "corrected_answer" + pub signal_type: String, // e.g., "feedback", "correction" + + #[serde(skip_serializing_if = "Option::is_none")] + pub properties: Option>, + + // Optional fields + #[serde(skip_serializing_if = "Option::is_none")] + pub user_id: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp: Option>, +} \ No newline at end of file From 6e33d059b906be88f5d73088d209ce0770a9a651 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Mon, 5 May 2025 11:32:24 -0600 Subject: [PATCH 2/2] remove unused logs --- .../BusterChartJS/BusterChartJSComponent.tsx | 3 - .../helpers/formatBarAndLineDataLabel.test.ts | 87 ++++++++++++++++++- .../helpers/formatBarAndLineDataLabel.ts | 2 +- .../useSeriesOptions/barSeriesBuilder.ts | 13 ++- .../ChatContext/useAutoChangeLayout.ts | 14 --- .../ChatLayoutContext/ChatLayoutContext.tsx | 1 - .../useLayoutConfig/useLayoutConfig.ts | 31 +------ .../useSelectedFile/useSelectedFile.ts | 4 - web/src/lib/objects.ts | 24 ++--- 9 files changed, 106 insertions(+), 73 deletions(-) diff --git a/web/src/components/ui/charts/BusterChartJS/BusterChartJSComponent.tsx b/web/src/components/ui/charts/BusterChartJS/BusterChartJSComponent.tsx index 6d1502934..0502a6da8 100644 --- a/web/src/components/ui/charts/BusterChartJS/BusterChartJSComponent.tsx +++ b/web/src/components/ui/charts/BusterChartJS/BusterChartJSComponent.tsx @@ -195,9 +195,6 @@ export const BusterChartJSComponent = React.memo( if (selectedChartType === 'combo') return [ChartHoverBarPlugin, ChartTotalizerPlugin]; return []; }, [selectedChartType]); - console.log('datasetOptions', datasetOptions); - console.log('data', data); - console.log('options', options); return ( diff --git a/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.test.ts b/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.test.ts index cacd01ea6..5d8471d5b 100644 --- a/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.test.ts +++ b/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.test.ts @@ -1,6 +1,6 @@ import { formatBarAndLineDataLabel } from './formatBarAndLineDataLabel'; import { ColumnLabelFormat } from '@/api/asset_interfaces/metric'; -import { Context } from 'chartjs-plugin-datalabels'; +import type { Context } from 'chartjs-plugin-datalabels'; describe('formatBarAndLineDataLabel', () => { it('formats a single value without percentage', () => { @@ -33,4 +33,89 @@ describe('formatBarAndLineDataLabel', () => { expect(result).toBe('1,234.56'); }); + + // Mock chart context + const createMockContext = (datasets: any[]): Partial => ({ + chart: { + data: { + datasets + }, + $totalizer: { + stackTotals: [100], + seriesTotals: [50] + } + } as any, + dataIndex: 0, + datasetIndex: 0 + }); + + describe('useStackTotal logic', () => { + const baseDataset = { hidden: false, isTrendline: false }; + + test('should use stack total when there are multiple visible datasets', () => { + const mockContext = createMockContext([baseDataset, { ...baseDataset }]) as Context; + + const result = formatBarAndLineDataLabel(25, mockContext, 'data-label', { + style: 'number', + columnType: 'number' + }); + + // 25 out of stack total (100) = 25% + expect(result).toBe('25%'); + }); + + test('should use stack total when percentageMode is stacked', () => { + const mockContext = createMockContext([baseDataset]) as Context; + + const result = formatBarAndLineDataLabel(25, mockContext, 'stacked', { + style: 'number', + columnType: 'number' + }); + + // 25 out of stack total (100) = 25% + expect(result).toBe('25%'); + }); + + test('should use series total for single dataset and non-stacked percentage mode', () => { + const mockContext = createMockContext([baseDataset]) as Context; + + const result = formatBarAndLineDataLabel(25, mockContext, 'data-label', { + style: 'number', + columnType: 'number' + }); + + // 25 out of series total (50) = 50% + expect(result).toBe('50%'); + }); + + test('should ignore hidden datasets when counting multiple datasets', () => { + const mockContext = createMockContext([ + baseDataset, + { ...baseDataset, hidden: true } + ]) as Context; + + const result = formatBarAndLineDataLabel(25, mockContext, 'data-label', { + style: 'number', + columnType: 'number' + }); + + // 25 out of series total (50) = 50% (since second dataset is hidden) + expect(result).toBe('50%'); + }); + + test('should ignore trendline datasets when counting multiple datasets', () => { + const mockContext = createMockContext([ + baseDataset, + { ...baseDataset, isTrendline: true } + ]) as Context; + + const result = formatBarAndLineDataLabel(25, mockContext, 'data-label', { + style: 'number', + columnType: 'number' + }); + + // 25 out of series total (50) = 50% (since second dataset is a trendline) + expect(result).toBe('50%'); + }); + }); }); diff --git a/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.ts b/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.ts index 34e4359e7..569e5fd9a 100644 --- a/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.ts +++ b/web/src/components/ui/charts/BusterChartJS/helpers/formatBarAndLineDataLabel.ts @@ -17,7 +17,7 @@ export const formatBarAndLineDataLabel = ( ); const hasMultipleDatasets = shownDatasets.length > 1; - const useStackTotal = !hasMultipleDatasets || percentageMode === 'stacked'; + const useStackTotal = hasMultipleDatasets || percentageMode === 'stacked'; const total: number = useStackTotal ? context.chart.$totalizer.stackTotals[context.dataIndex] diff --git a/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts b/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts index 5edcf97de..64563063b 100644 --- a/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts +++ b/web/src/components/ui/charts/BusterChartJS/hooks/useSeriesOptions/barSeriesBuilder.ts @@ -332,13 +332,12 @@ const getFormattedValueAndSetBarDataLabels = ( } ) => { const rawValue = context.dataset.data[context.dataIndex] as number; - const percentageModesMatch = context.chart.$barDataLabelsPercentageMode === percentageMode; - const currentValue = percentageModesMatch - ? context.chart.$barDataLabels?.[context.datasetIndex]?.[context.dataIndex] || '' - : ''; - - const formattedValue = - currentValue || formatBarAndLineDataLabel(rawValue, context, percentageMode, columnLabelFormat); + const formattedValue = formatBarAndLineDataLabel( + rawValue, + context, + percentageMode, + columnLabelFormat + ); // Store only the formatted value, rotation is handled globally setBarDataLabelsManager(context, formattedValue, percentageMode); diff --git a/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts b/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts index 425bb85c5..2a905af66 100644 --- a/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts +++ b/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts @@ -52,14 +52,6 @@ export const useAutoChangeLayout = ({ const hasReasoning = !!lastReasoningMessageId; useEffect(() => { - console.log( - 'REASONING: useEffect', - isCompletedStream, - hasReasoning, - chatId, - lastMessageId, - isFinishedReasoning - ); //this will trigger when the chat is streaming and is has not completed yet (new chat) if ( !isCompletedStream && @@ -70,14 +62,11 @@ export const useAutoChangeLayout = ({ ) { previousLastMessageId.current = lastMessageId; - console.log('REASONING: FLIP TO REASONING!', lastMessageId); - onSetSelectedFile({ id: lastMessageId, type: 'reasoning', versionNumber: undefined }); } //this will when the chat is completed and it WAS streaming else if (isCompletedStream && previousIsCompletedStream === false) { - console.log('REASONING: SELECT STREAMING FILE'); const chatMessage = getChatMessageMemoized(lastMessageId); const lastFileId = findLast(chatMessage?.response_message_ids, (id) => { const responseMessage = chatMessage?.response_messages[id]; @@ -97,7 +86,6 @@ export const useAutoChangeLayout = ({ }); if (link) { - console.log('auto change layout', link); onChangePage(link); } return; @@ -105,7 +93,6 @@ export const useAutoChangeLayout = ({ } //this will trigger on a page refresh and the chat is completed else if (isCompletedStream && chatId) { - console.log('REASONING: SELECT INITIAL CHAT FILE - PAGE LOAD'); const isChatOnlyMode = !metricId && !dashboardId && !messageId; if (isChatOnlyMode) { return; @@ -122,7 +109,6 @@ export const useAutoChangeLayout = ({ }); if (href) { - console.log('auto change layout2', href); onChangePage(href); } } diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/ChatLayoutContext.tsx b/web/src/layouts/ChatLayout/ChatLayoutContext/ChatLayoutContext.tsx index 45adcccb8..f053ada23 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/ChatLayoutContext.tsx +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/ChatLayoutContext.tsx @@ -17,7 +17,6 @@ export const useChatLayoutContext = ({ appSplitterRef }: UseLayoutConfigProps) = const chatParams = useGetChatParams(); const animateOpenSplitter = useMemoizedFn((side: 'left' | 'right' | 'both') => { - console.log('animateOpenSplitter', !!appSplitterRef.current, { side }); if (appSplitterRef.current) { const { animateWidth, sizes } = appSplitterRef.current; const leftSize = sizes[0] ?? 0; diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts b/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts index bc16551c6..2e4b1dab6 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts @@ -88,11 +88,6 @@ export const useLayoutConfig = ({ fileId?: string | undefined; secondaryView?: FileViewSecondary; }) => { - console.log('onSetFileView', { - fileView, - fileId: fileIdProp, - secondaryView - }); const fileId = fileIdProp ?? selectedFileId; if (!fileId) { onCollapseFileClick(); @@ -146,11 +141,7 @@ export const useLayoutConfig = ({ const closeSecondaryView = useMemoizedFn(async () => { if (!selectedFileId || !selectedFileViewConfig || !selectedFileView) return; - console.log('closeSecondaryView', { - selectedFileId, - selectedFileViewConfig, - selectedFileView - }); + setFileViews((prev) => { return create(prev, (draft) => { if (!draft[selectedFileId]?.fileViewConfig?.[selectedFileView]) return; @@ -162,9 +153,7 @@ export const useLayoutConfig = ({ }); const onCollapseFileClick = useMemoizedFn(async () => { - console.log('onCollapseFileClick'); const isSecondaryViewOpen = !!selectedFileViewSecondary; - console.log('isSecondaryViewOpen', chatId, isSecondaryViewOpen); if (isSecondaryViewOpen) { closeSecondaryView(); @@ -190,15 +179,6 @@ export const useLayoutConfig = ({ //we need to use for when the user clicks the back or forward in the browser useUpdateEffect(() => { - console.log('useUpdateEffect', { - metricId, - secondaryView, - chatId, - dashboardId, - messageId, - currentRoute - }); - const newInitialFileViews = initializeFileViews({ secondaryView, metricId, @@ -218,17 +198,8 @@ export const useLayoutConfig = ({ currentRoute }); - console.log('isFileViewsChanged', isFileViewsChanged); - if (!isFileViewsChanged) return; - console.log('setting file view', { - newInitialFileViews, - fileId, - fileView, - secondaryView - }); - onSetFileView({ fileId, fileView, diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts index 7f8b2d9db..e1665a42e 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts @@ -31,9 +31,7 @@ export const useSelectedFile = ({ * @param file */ const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => { - console.log('onSetSelectedFile', file); const handleFileCollapse = shouldCloseSplitter(file, selectedFile, appSplitterRef); - console.log('handleFileCollapse', handleFileCollapse); if (file && chatParams.chatId) { const link = assetParamsToRoute({ @@ -43,8 +41,6 @@ export const useSelectedFile = ({ versionNumber: file?.versionNumber }); - console.log('link', link); - if (link) onChangePage(link); } diff --git a/web/src/lib/objects.ts b/web/src/lib/objects.ts index 56f6645e2..7f7fba495 100644 --- a/web/src/lib/objects.ts +++ b/web/src/lib/objects.ts @@ -47,24 +47,24 @@ export const compareObjectsByKeys = ( if (typeof val1 === 'object' && typeof val2 === 'object') { const itWasEqual = isEqual(val1, val2) || isEqual(JSON.stringify(val1), JSON.stringify(val2)); - if (!itWasEqual) { - console.log('--------------NESTED KEYS NOT EQUAL------------------'); - console.log('KEY', key); - console.log('ORIGINAL', val1); - console.log('NEW', val2); - } + // if (!itWasEqual) { + // console.log('--------------NESTED KEYS NOT EQUAL------------------'); + // console.log('KEY', key); + // console.log('ORIGINAL', val1); + // console.log('NEW', val2); + // } return itWasEqual; } const itWasEqual = isEqual(val1, val2); - if (!itWasEqual) { - console.log('--------------KEYS NOT EQUAL------------------'); - console.log('KEY', key); - console.log('ORIGINAL', val1); - console.log('NEW', val2); - } + // if (!itWasEqual) { + // console.log('--------------KEYS NOT EQUAL------------------'); + // console.log('KEY', key); + // console.log('ORIGINAL', val1); + // console.log('NEW', val2); + // } return itWasEqual; });