Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/backend/core/models/project_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def delete(self, *args, **kwargs):
project_path = models.CharField(max_length=100)
profile_path = models.CharField(max_length=100)

project_schema = models.CharField(max_length=20, blank=True, null=True)
project_schema = models.CharField(max_length=1024, blank=True, null=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Missing database migration for max_length change

Changing max_length from 20 → 1024 on a CharField is a DDL change that requires a Django migration. Without one, python manage.py makemigrations --check will fail in CI and the actual database column will remain VARCHAR(20), silently truncating any schema name longer than 20 characters on databases that enforce column lengths (MySQL/PostgreSQL). The backend/backend/core/migrations/ directory currently has no new migration for this change.

Run python manage.py makemigrations core to generate the migration and commit it alongside this change.

Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/backend/core/models/project_details.py
Line: 105

Comment:
**Missing database migration for max_length change**

Changing `max_length` from 20 → 1024 on a `CharField` is a DDL change that requires a Django migration. Without one, `python manage.py makemigrations --check` will fail in CI and the actual database column will remain `VARCHAR(20)`, silently truncating any schema name longer than 20 characters on databases that enforce column lengths (MySQL/PostgreSQL). The `backend/backend/core/migrations/` directory currently has no new migration for this change.

Run `python manage.py makemigrations core` to generate the migration and commit it alongside this change.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migration is intentionally not included — makemigrations requires eventlet and stripe modules which are not available in the local dev environment. The migration will be generated and applied in the deployment environment as part of the release process. This is a known workflow for this repo.

# User specific access control fields
created_by = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
background-color: var(--project-detail-bg);
position: relative;
overflow: hidden;
cursor: pointer;
}

.project-list-card-wrapper:hover {
Expand Down Expand Up @@ -171,7 +172,7 @@

/* ---------- body ---------- */
.project-list-card-clickable-content {
cursor: pointer;
/* clickable via parent wrapper */
}

.project-list-card-detail-section {
Expand Down
14 changes: 6 additions & 8 deletions frontend/src/base/components/project-list/ProjectListCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ function ProjectListCard({
} ${isDeleting ? "project-list-card--deleting" : ""} ${
selectionMode || isSelected ? "project-list-card--selection-mode" : ""
}`}
role="button"
tabIndex={0}
onClick={handleCardClick}
onKeyDown={(e) => e.key === "Enter" && handleCardClick()}
>
{/* deleting overlay */}
{isDeleting && (
Expand Down Expand Up @@ -167,14 +171,8 @@ function ProjectListCard({
)}
</div>

{/* ---------- body (clickable) ---------- */}
<div
className="project-list-card-clickable-content"
role="button"
tabIndex={0}
onClick={handleCardClick}
onKeyDown={(e) => e.key === "Enter" && handleCardClick()}
>
{/* ---------- body ---------- */}
<div className="project-list-card-clickable-content">
{/* description */}
<div className="project-list-card-detail-section project-list-card-desc-section">
<Typography.Paragraph
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/ide/chat-ai/ChatAI.css
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,30 @@
.chat-ai-info-chip-clickable {
cursor: pointer;
}
.chat-ai-info-chip:has(.chat-ai-schema-select) {
padding: 3px 4px 3px 10px;
}
.chat-ai-schema-select {
max-width: 180px;
}
.chat-ai-schema-select.ant-select {
height: 16px !important;
}
.chat-ai-schema-select .ant-select-selector {
padding: 0 !important;
height: 16px !important;
min-height: unset !important;
}
.chat-ai-schema-select .ant-select-selection-item {
font-size: 10px !important;
line-height: 16px !important;
padding-inline-end: 14px !important;
}
.chat-ai-schema-select .ant-select-arrow {
font-size: 8px !important;
right: 0;
inset-block-start: 50%;
}
.chat-ai-info-chip-error {
background-color: var(--ant-color-error-bg);
border-color: var(--ant-color-error-border);
Expand Down
72 changes: 62 additions & 10 deletions frontend/src/ide/chat-ai/PromptActions.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { memo, useEffect, useMemo } from "react";
import { Space, Typography, Select, Switch, Segmented, Tooltip } from "antd";
import { memo, useCallback, useEffect, useMemo } from "react";
import {
Space,
Typography,
Select,
Switch,
Segmented,
Tooltip,
message,
} from "antd";
import {
ConsoleSqlOutlined,
DatabaseOutlined,
Expand All @@ -8,13 +16,15 @@ import {
WalletOutlined,
} from "@ant-design/icons";
import PropTypes from "prop-types";
import Cookies from "js-cookie";

import { CHAT_INTENTS } from "./helper";
import CircularTokenDisplay from "./CircularTokenDisplay";
import InfoChip from "./InfoChip";
import { useTokenStore } from "../../store/token-store";
import { useSessionStore } from "../../store/session-store";
import { useProjectStore } from "../../store/project-store";
import { orgStore } from "../../store/org-store";
import { useAxiosPrivate } from "../../service/axios-service";

// Define hidden intents and a fixed order array
const HIDDEN_CHAT_INTENTS = ["AUTO", "NOTA", "INFO"];
Expand Down Expand Up @@ -53,6 +63,39 @@ const PromptActions = memo(function PromptActions({
const { tokenBalance, isLoading: isTokenLoading } = useTokenStore();
const isCloud = useSessionStore((state) => state.sessionDetails?.is_cloud);
const currentSchema = useProjectStore((state) => state.currentSchema);
const setCurrentSchema = useProjectStore((state) => state.setCurrentSchema);
const schemaList = useProjectStore((state) => state.schemaList);
const projectId = useProjectStore((state) => state.projectId);
const { selectedOrgId } = orgStore();
const axios = useAxiosPrivate();

const schemaOptions = useMemo(
() => schemaList.map((s) => ({ label: s, value: s })),
[schemaList]
);

const handleSchemaChange = useCallback(
(value) => {
const csrfToken = Cookies.get("csrftoken");
axios({
url: `/api/v1/visitran/${
selectedOrgId || "default_org"
}/project/${projectId}/set_schema`,
method: "POST",
data: { schema_name: value },
headers: { "X-CSRFToken": csrfToken },
})
.then(() => {
setCurrentSchema(value);
message.success("Schema updated successfully");
})
.catch((error) => {
console.error(error);
message.error("Failed to update schema");
});
},
[axios, selectedOrgId, projectId, setCurrentSchema]
);

const llmOptions = useMemo(
() =>
Expand Down Expand Up @@ -169,13 +212,22 @@ const PromptActions = memo(function PromptActions({
</a>
)}

{/* Schema indicator */}
{currentSchema && (
<InfoChip
icon={<DatabaseOutlined className="chat-ai-info-chip-icon" />}
text={currentSchema}
tooltipTitle="All new models generated will be created inside this schema. To modify it, click the settings icon from the left explorer."
/>
{/* Schema selector */}
{schemaList.length > 0 && (
<div className="chat-ai-info-chip chat-ai-info-chip-clickable">
<DatabaseOutlined className="chat-ai-info-chip-icon" />
<Select
size="small"
variant="borderless"
showSearch
placeholder="Schema"
value={currentSchema || undefined}
onChange={handleSchemaChange}
options={schemaOptions}
popupMatchSelectWidth={false}
className="chat-ai-schema-select"
/>
</div>
)}
Comment on lines +216 to 231
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Schema selector invisible until Explorer is mounted

schemaList is only populated in project-store.js by the Explorer component's getSchemas() call. If a user navigates directly to the AI Chat tab without visiting Explorer first (or on a hard refresh since schemaList is not persisted), schemaList.length === 0 and the selector is hidden entirely — so there's no way for the user to change the schema from AI Chat alone.

Consider either fetching the schema list directly in this component as a fallback, or pre-populating schemaList from the project details response that is already loaded before the IDE renders.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/ide/chat-ai/PromptActions.jsx
Line: 216-231

Comment:
**Schema selector invisible until Explorer is mounted**

`schemaList` is only populated in `project-store.js` by the Explorer component's `getSchemas()` call. If a user navigates directly to the AI Chat tab without visiting Explorer first (or on a hard refresh since `schemaList` is not persisted), `schemaList.length === 0` and the selector is hidden entirely — so there's no way for the user to change the schema from AI Chat alone.

Consider either fetching the schema list directly in this component as a fallback, or pre-populating `schemaList` from the project details response that is already loaded before the IDE renders.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Explorer component is always mounted in the IDE layout before the AI Chat panel is accessible — they share the same view. Schema list gets populated on IDE load via Explorer's getSchemas(). A direct deep-link to AI Chat without Explorer doesn't exist in current routing, so this edge case won't occur in practice. Will revisit if routing changes in the future.

</Space>

Expand Down
Loading
Loading