Skip to content

Commit dc9e593

Browse files
Merge branch 'main' of github.com:superluminalengineering/superluminal-react
2 parents 50b3344 + 695b7c3 commit dc9e593

File tree

5 files changed

+30
-16
lines changed

5 files changed

+30
-16
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "superluminal-react",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "The official front-end React component for the Superluminal API.",
55
"keywords": [
66
"dashboard",

src/components/AssistantView.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
8484
getWatermarkView(): any {
8585
return <a style={styles.watermark} href='https://www.superluminal.dev' target='_blank'>
8686
<span style={{ opacity: 0.4, fontSize: '11px' }}>Powered by</span>
87-
<img src={LogoText} height="14px" style={{ opacity: 0.4, marginTop: '1px' }} />
87+
<img src={LogoText} height="14px" style={{ opacity: 0.4, marginTop: '1px' }} draggable={false} />
8888
</a>
8989
}
9090

@@ -109,7 +109,7 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
109109
case 'assistant':
110110
if ('text' in message.content) {
111111
return <div key={message.id} style={styles.messageContainer}>
112-
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" />
112+
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" draggable={false} />
113113
<div style={{ ...styles.assistantMessage, ...assistantMessageStyle }}>{message.content.text}</div>
114114
</div>
115115
} else if ('plot' in message.content) {
@@ -120,7 +120,7 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
120120
const height = ((plot.layout.width * width) / plot.layout.height);
121121
const layout = { ...plot.layout, width, height, margin: { t: 30, b: 10, l: 10, r: 10, pad: 0 } };
122122
return <div key={message.id} style={styles.messageContainer}>
123-
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" />
123+
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" draggable={false} />
124124
<div style={{ display: 'flex', flexDirection: 'column', rowGap: '12px' }}>
125125
<div style={{ ...styles.assistantMessage, ...{ maxWidth: '100%', background: '#FFFFFF' }, ...assistantMessageStyle }}>
126126
<Plot data={plot.data} layout={layout} config={{ toImageButtonOptions: { scale: 3 } }} />
@@ -131,8 +131,8 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
131131
const table = message.content.table;
132132
return <div key={message.id} style={styles.messageContainer}>
133133
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
134-
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" />
135-
<img src={IconExpand} width="20px" height="20px" onClick={() => this.expandTable(table)} />
134+
<img src={LogoInverted} style={styles.profilePictureView} width="24px" height="24px" draggable={false} />
135+
<img src={IconExpand} width="20px" height="20px" onClick={() => this.expandTable(table)} draggable={false} />
136136
</div>
137137
<div style={{ ...styles.assistantMessage, ...{ maxWidth: '100%', background: '#FFFFFF' }, ...assistantMessageStyle }}>
138138
<TablePreview table={table} />
@@ -153,12 +153,16 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
153153
document.body
154154
)}
155155
</div>
156-
} else {
156+
} else if (sessionState == 'initializing' || sessionState == 'waiting_for_data' || sessionState == 'validating_data') {
157157
return <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }}>
158-
<img src='https://superluminal.dev/images/ai.webp' width="64px" height="64px" />
158+
<img src='https://superluminal.dev/images/ai.webp' width="64px" height="64px" draggable={false} />
159159
<div style={{ fontSize: '20px', fontWeight: 600, color: '#000000', marginTop: '8px' }}>Loading</div>
160160
</div>
161-
}
161+
} else { // 'error' | 'unavailable'
162+
return <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', padding: '8px' }}>
163+
<div style={{ fontSize: '14px', fontWeight: 600, color: '#000000', marginTop: '8px', textAlign: 'center' }}>An unexpected error occurred.<br />Please try again later.</div>
164+
</div>
165+
}
162166
}
163167

164168
getInputView(): any {
@@ -188,7 +192,7 @@ class AssistantView extends React.Component<Props, State> implements SessionCont
188192
this.setState({ user });
189193
}
190194

191-
onSessionStateUpdated(sessionState: SessionState) {
195+
onSessionStateUpdated(sessionState: SessionState, error: string | null) {
192196
this.setState({ sessionState });
193197
}
194198

src/controllers/SessionController.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { SLWebSocket, SLWebSocketEventListener } from "../networking/WebSocket";
88
import { TablePage, isTablePage } from "../models/TableInfo";
99

1010
export interface SessionControllerEventListener {
11-
onSessionStateUpdated?: (sessionState: SessionState) => void;
11+
onSessionStateUpdated?: (sessionState: SessionState, error: string | null) => void;
1212
onChatMessagesUpdated?: (chatMessages: ChatMessage[]) => void;
1313
onTablePageReceived?: (page: TablePage) => void;
1414
}
@@ -18,6 +18,7 @@ class SessionController implements SLWebSocketEventListener {
1818
user: { id: string, name: string } | null = null;
1919
projectID: string = "main";
2020
sessionState: SessionState = 'initializing';
21+
error: string | null = null;
2122
authToken: string | null = null;
2223
chatMessages: ChatMessage[] = [];
2324

@@ -56,7 +57,8 @@ class SessionController implements SLWebSocketEventListener {
5657
Server.getSession(this.authToken)
5758
.then((response) => {
5859
this.sessionState = response.session_state;
59-
this.listeners.forEach((listener) => listener.onSessionStateUpdated?.(response.session_state));
60+
this.error = response.error;
61+
this.listeners.forEach((listener) => listener.onSessionStateUpdated?.(response.session_state, response.error));
6062
this.chatMessages = response.chat_history;
6163
this.listeners.forEach((listener) => listener.onChatMessagesUpdated?.(response.chat_history));
6264
})
@@ -113,10 +115,12 @@ class SessionController implements SLWebSocketEventListener {
113115

114116
onSessionStateUpdated(json: JSON) {
115117
const sessionState = json['session_state'];
118+
const error = json['error'];
116119
if (!sessionState) { return; }
117120
this.sessionState = sessionState;
118-
console.log(`Session state: ${sessionState}`);
119-
this.listeners.forEach((listener) => listener.onSessionStateUpdated?.(sessionState));
121+
this.error = error;
122+
console.log(`Session state: ${sessionState}` + (error ? ` (${error})` : ''));
123+
this.listeners.forEach((listener) => listener.onSessionStateUpdated?.(sessionState, error));
120124
}
121125

122126
onAssistantStateUpdated(json: JSON) {

src/models/SessionState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
export type SessionState = 'initializing' | 'waiting_for_data' | 'ready' | 'unavailable';
2+
export type SessionState = 'initializing' | 'waiting_for_data' | 'validating_data' | 'ready' | 'error' | 'unavailable';

src/networking/Server.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
import { ChatMessage } from "../models/ChatMessage";
33
import { SessionState } from "../models/SessionState";
44

5+
type GetSessionResponse = {
6+
session_state: SessionState,
7+
error: string | null,
8+
chat_history: ChatMessage[]
9+
}
10+
511
class Server {
612

713
static baseURL = "https://app.getluminal.com";
814

9-
static getSession(authToken: string): Promise<{ session_state: SessionState, chat_history: ChatMessage[] }> {
15+
static getSession(authToken: string): Promise<GetSessionResponse> {
1016
return fetch(`${Server.baseURL}/session`, {
1117
method: "GET",
1218
headers: {

0 commit comments

Comments
 (0)