Skip to content

Commit f76c2f7

Browse files
FIX: Display Current Schema in Chat AI Prompt Actions (#30)
* feat: move currentSchema state to global zustand store - Add currentSchema and setCurrentSchema to project-store - Update explorer-component to use store instead of local state - Enables sharing schema state across components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add reusable InfoChip component - Create InfoChip.jsx for pill-shaped chip UI pattern - Add CSS classes for InfoChip styling in ChatAI.css - Supports icon, text, tooltip, and optional className prop 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: use InfoChip in CircularTokenDisplay and PromptActions - Refactor CircularTokenDisplay to use InfoChip for credit display - Add schema chip to PromptActions using InfoChip component - Display current schema name with tooltip next to credit balance 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: use InfoChip for "No Credits" state in CircularTokenDisplay - Add error variant CSS class (chat-ai-info-chip-error) - Replace inline JSX with InfoChip component for consistency - Reduces code duplication and improves maintainability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: reset currentSchema on explorer unmount Add cleanup effect to reset currentSchema when IdeExplorer unmounts, preventing stale schema data from showing in other views. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: use selector pattern for setCurrentSchema Move setCurrentSchema to use selector pattern for consistency with currentSchema, following the same approach used in PromptActions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b78ec29 commit f76c2f7

File tree

6 files changed

+143
-88
lines changed

6 files changed

+143
-88
lines changed

frontend/src/ide/chat-ai/ChatAI.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,37 @@
417417
transition: all 0.3s ease;
418418
white-space: nowrap;
419419
}
420+
/* InfoChip component styles */
421+
.chat-ai-info-chip {
422+
display: inline-flex;
423+
align-items: center;
424+
gap: 6px;
425+
padding: 4px 12px;
426+
border-radius: 100px;
427+
background-color: var(--content-bg);
428+
border: 1px solid var(--border-color-3);
429+
cursor: default;
430+
transition: all 0.3s ease;
431+
}
432+
.chat-ai-info-chip-text {
433+
font-size: 10px;
434+
white-space: nowrap;
435+
}
436+
.chat-ai-info-chip-icon {
437+
font-size: 12px;
438+
color: var(--icons-color);
439+
}
440+
.chat-ai-info-chip-clickable {
441+
cursor: pointer;
442+
}
443+
.chat-ai-info-chip-error {
444+
background-color: var(--ant-color-error-bg);
445+
border-color: var(--ant-color-error-border);
446+
}
447+
.chat-ai-info-chip-error .chat-ai-info-chip-icon,
448+
.chat-ai-info-chip-error .chat-ai-info-chip-text {
449+
color: var(--ant-color-error);
450+
}
420451
.chat-ai-manage-credits-link:hover {
421452
color: var(--icons-color);
422453
border-color: var(--icons-color);

frontend/src/ide/chat-ai/CircularTokenDisplay.jsx

Lines changed: 14 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useEffect, useState } from "react";
2-
import { Tooltip, Typography, Space, Spin, theme } from "antd";
2+
import { Tooltip, Space, Spin, theme } from "antd";
33
import { LoadingOutlined, WalletOutlined } from "@ant-design/icons";
44
import PropTypes from "prop-types";
5+
import InfoChip from "./InfoChip";
56

67
const { useToken } = theme;
78

@@ -157,41 +158,12 @@ const CircularTokenDisplay = ({ tokenData, onBuyTokens, isLoading }) => {
157158
);
158159

159160
return (
160-
<Tooltip
161-
title={noCreditsTooltip}
162-
color={token.colorBgElevated}
163-
overlayInnerStyle={{
164-
border: `1px solid ${token.colorBorder}`,
165-
borderRadius: "8px",
166-
}}
167-
>
168-
<div
169-
style={{
170-
display: "inline-flex",
171-
alignItems: "center",
172-
gap: "6px",
173-
padding: "4px 12px",
174-
borderRadius: "100px",
175-
backgroundColor: token.colorErrorBg,
176-
border: `1px solid ${token.colorErrorBorder}`,
177-
cursor: "default",
178-
transition: "all 0.3s ease",
179-
}}
180-
>
181-
<WalletOutlined
182-
style={{ fontSize: "12px", color: token.colorError }}
183-
/>
184-
<Typography.Text
185-
className="chat-ai-prompt-actions-monaco-font-size-10"
186-
style={{
187-
whiteSpace: "nowrap",
188-
color: token.colorError,
189-
}}
190-
>
191-
No Credits
192-
</Typography.Text>
193-
</div>
194-
</Tooltip>
161+
<InfoChip
162+
icon={<WalletOutlined className="chat-ai-info-chip-icon" />}
163+
text="No Credits"
164+
tooltipTitle={noCreditsTooltip}
165+
className="chat-ai-info-chip-error"
166+
/>
195167
);
196168
}
197169

@@ -200,39 +172,12 @@ const CircularTokenDisplay = ({ tokenData, onBuyTokens, isLoading }) => {
200172
const formattedCredits = creditsLeft.toLocaleString();
201173

202174
return (
203-
<Tooltip
204-
title={tooltipContent}
205-
placement="top"
206-
color={token.colorBgElevated}
207-
overlayInnerStyle={{
208-
border: `1px solid ${token.colorBorder}`,
209-
borderRadius: "8px",
210-
}}
211-
>
212-
<div
213-
style={{
214-
display: "inline-flex",
215-
alignItems: "center",
216-
gap: "6px",
217-
padding: "4px 12px",
218-
borderRadius: "100px", // Pill shape
219-
backgroundColor: token.colorBgContainer,
220-
border: `1px solid ${token.colorBorder}`,
221-
cursor: "pointer",
222-
transition: "all 0.3s ease",
223-
}}
224-
>
225-
<WalletOutlined style={{ fontSize: "12px", color: token.colorText }} />
226-
<Typography.Text
227-
className="chat-ai-prompt-actions-monaco-font-size-10"
228-
style={{
229-
whiteSpace: "nowrap",
230-
}}
231-
>
232-
{formattedCredits} credits left
233-
</Typography.Text>
234-
</div>
235-
</Tooltip>
175+
<InfoChip
176+
icon={<WalletOutlined className="chat-ai-info-chip-icon" />}
177+
text={`${formattedCredits} credits left`}
178+
tooltipTitle={tooltipContent}
179+
className="chat-ai-info-chip-clickable"
180+
/>
236181
);
237182
};
238183

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Tooltip, Typography, theme } from "antd";
2+
import PropTypes from "prop-types";
3+
4+
const { useToken } = theme;
5+
6+
const InfoChip = ({
7+
icon,
8+
text,
9+
tooltipTitle,
10+
tooltipPlacement = "top",
11+
className = "",
12+
}) => {
13+
const { token } = useToken();
14+
15+
const chip = (
16+
<div className={`chat-ai-info-chip ${className}`}>
17+
{icon}
18+
<Typography.Text className="chat-ai-info-chip-text">
19+
{text}
20+
</Typography.Text>
21+
</div>
22+
);
23+
24+
if (!tooltipTitle) return chip;
25+
26+
return (
27+
<Tooltip
28+
title={tooltipTitle}
29+
placement={tooltipPlacement}
30+
color={token.colorBgElevated}
31+
overlayInnerStyle={{
32+
border: `1px solid ${token.colorBorder}`,
33+
borderRadius: "8px",
34+
}}
35+
>
36+
{chip}
37+
</Tooltip>
38+
);
39+
};
40+
41+
InfoChip.propTypes = {
42+
icon: PropTypes.node.isRequired,
43+
text: PropTypes.string.isRequired,
44+
tooltipTitle: PropTypes.node,
45+
tooltipPlacement: PropTypes.string,
46+
className: PropTypes.string,
47+
};
48+
49+
export default InfoChip;

frontend/src/ide/chat-ai/PromptActions.jsx

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { memo, useEffect, useMemo } from "react";
22
import { Space, Typography, Select, Switch, Segmented, Tooltip } from "antd";
33
import {
44
ConsoleSqlOutlined,
5+
DatabaseOutlined,
56
MessageOutlined,
67
RetweetOutlined,
78
WalletOutlined,
@@ -10,8 +11,10 @@ import PropTypes from "prop-types";
1011

1112
import { CHAT_INTENTS } from "./helper";
1213
import CircularTokenDisplay from "./CircularTokenDisplay";
14+
import InfoChip from "./InfoChip";
1315
import { useTokenStore } from "../../store/token-store";
1416
import { useSessionStore } from "../../store/session-store";
17+
import { useProjectStore } from "../../store/project-store";
1518

1619
// Define hidden intents and a fixed order array
1720
const HIDDEN_CHAT_INTENTS = ["AUTO", "NOTA", "INFO"];
@@ -49,6 +52,7 @@ const PromptActions = memo(function PromptActions({
4952
// Get token balance from store
5053
const { tokenBalance, isLoading: isTokenLoading } = useTokenStore();
5154
const isCloud = useSessionStore((state) => state.sessionDetails?.is_cloud);
55+
const currentSchema = useProjectStore((state) => state.currentSchema);
5256

5357
const llmOptions = useMemo(
5458
() =>
@@ -145,24 +149,35 @@ const PromptActions = memo(function PromptActions({
145149
)}
146150
</Space>
147151

148-
{/* Cloud: full credit display | OSS: link to billing page */}
149-
{isCloud ? (
150-
<CircularTokenDisplay
151-
tokenData={tokenBalance}
152-
onBuyTokens={onBuyTokens}
153-
isLoading={isTokenLoading}
154-
/>
155-
) : (
156-
<a
157-
href="https://us.app.visitran.com/project/setting/subscriptions"
158-
target="_blank"
159-
rel="noopener noreferrer"
160-
className="chat-ai-manage-credits-link"
161-
>
162-
<WalletOutlined />
163-
<span>Manage Credits</span>
164-
</a>
165-
)}
152+
<Space>
153+
{/* Cloud: full credit display | OSS: link to billing page */}
154+
{isCloud ? (
155+
<CircularTokenDisplay
156+
tokenData={tokenBalance}
157+
onBuyTokens={onBuyTokens}
158+
isLoading={isTokenLoading}
159+
/>
160+
) : (
161+
<a
162+
href="https://us.app.visitran.com/project/setting/subscriptions"
163+
target="_blank"
164+
rel="noopener noreferrer"
165+
className="chat-ai-manage-credits-link"
166+
>
167+
<WalletOutlined />
168+
<span>Manage Credits</span>
169+
</a>
170+
)}
171+
172+
{/* Schema indicator */}
173+
{currentSchema && (
174+
<InfoChip
175+
icon={<DatabaseOutlined className="chat-ai-info-chip-icon" />}
176+
text={currentSchema}
177+
tooltipTitle="All new models generated will be created inside this schema. To modify it, click the settings icon from the left explorer."
178+
/>
179+
)}
180+
</Space>
166181

167182
<div>
168183
<Tooltip

frontend/src/ide/explorer/explorer-component.jsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ const IdeExplorer = ({
8080
projectName,
8181
projectId,
8282
} = useProjectStore();
83+
const currentSchema = useProjectStore((state) => state.currentSchema);
84+
const setCurrentSchema = useProjectStore((state) => state.setCurrentSchema);
85+
86+
// Reset currentSchema on unmount to prevent stale data
87+
useEffect(() => {
88+
return () => {
89+
setCurrentSchema("");
90+
};
91+
}, [setCurrentSchema]);
92+
8393
const expService = explorerService();
8494
const [tree, setTree] = useState([]);
8595
const [expandedKeys, setExpandedKeys] = useState([]);
@@ -88,7 +98,6 @@ const IdeExplorer = ({
8898
const [rightClickedItem, setRightClickedItem] = useState();
8999
const [selectedKey, setSelectedKey] = useState(currentNode);
90100
const [openNameModal, setOpenNameModal] = useState(false);
91-
const [currentSchema, setCurrentSchema] = useState("");
92101
const [newSchemaName, setNewSchemaName] = useState("");
93102
const [isSchemaModalOpen, setIsSchemaModalOpen] = useState(false);
94103
const [schemaMenu, setSchemaMenu] = useState([]);

frontend/src/store/project-store.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const STORE_VARIABLES = {
88
previewTimeTravel: false,
99
projectId: "",
1010
renamedModel: {},
11+
currentSchema: "",
1112
};
1213

1314
const useProjectStore = create(
@@ -65,6 +66,11 @@ const useProjectStore = create(
6566
return { renamedModel: modelNames };
6667
});
6768
},
69+
setCurrentSchema: (schema) => {
70+
setState(() => {
71+
return { currentSchema: schema };
72+
});
73+
},
6874
}),
6975
{
7076
name: "project-tab-storage",

0 commit comments

Comments
 (0)