diff --git a/backend/backend/core/models/project_details.py b/backend/backend/core/models/project_details.py
index 02659de..e26804d 100644
--- a/backend/backend/core/models/project_details.py
+++ b/backend/backend/core/models/project_details.py
@@ -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)
# User specific access control fields
created_by = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
diff --git a/frontend/src/base/components/project-list/ProjectListCard.css b/frontend/src/base/components/project-list/ProjectListCard.css
index a912020..6878ebf 100644
--- a/frontend/src/base/components/project-list/ProjectListCard.css
+++ b/frontend/src/base/components/project-list/ProjectListCard.css
@@ -9,6 +9,7 @@
background-color: var(--project-detail-bg);
position: relative;
overflow: hidden;
+ cursor: pointer;
}
.project-list-card-wrapper:hover {
@@ -171,7 +172,7 @@
/* ---------- body ---------- */
.project-list-card-clickable-content {
- cursor: pointer;
+ /* clickable via parent wrapper */
}
.project-list-card-detail-section {
diff --git a/frontend/src/base/components/project-list/ProjectListCard.jsx b/frontend/src/base/components/project-list/ProjectListCard.jsx
index 131755d..f180428 100644
--- a/frontend/src/base/components/project-list/ProjectListCard.jsx
+++ b/frontend/src/base/components/project-list/ProjectListCard.jsx
@@ -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 && (
@@ -141,6 +145,7 @@ function ProjectListCard({
if (ShareProjectModal) setIsShareModalOpen(true);
}}
onKeyDown={(e) => {
+ e.stopPropagation();
if (e.key === "Enter" && ShareProjectModal)
setIsShareModalOpen(true);
}}
@@ -167,14 +172,8 @@ function ProjectListCard({
)}
- {/* ---------- body (clickable) ---------- */}
-
e.key === "Enter" && handleCardClick()}
- >
+ {/* ---------- body ---------- */}
+
{/* description */}
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(
() =>
@@ -169,13 +212,22 @@ const PromptActions = memo(function PromptActions({
)}
- {/* Schema indicator */}
- {currentSchema && (
- }
- 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 && (
+
+
+
+
)}
diff --git a/frontend/src/ide/editor/no-code-configuration/configure-source-destination.jsx b/frontend/src/ide/editor/no-code-configuration/configure-source-destination.jsx
index 5a0bc4c..99f860d 100644
--- a/frontend/src/ide/editor/no-code-configuration/configure-source-destination.jsx
+++ b/frontend/src/ide/editor/no-code-configuration/configure-source-destination.jsx
@@ -204,178 +204,143 @@ function ConfigureSourceDestination({
}, [reference]);
return (
<>
-
-
+
+
+
+ Hierarchy
+
+
+ {
+ const newModelType = e.target.value;
+ if (newModelType === "root") {
+ setPrevReference(reference.length ? reference : []);
+ setReference([]);
+ } else {
+ setReference(prevReference.length ? prevReference : reference);
+ }
+ setModelType(newModelType);
+ }}
+ className="mb-10"
>
-
-
-
-
- Hierarchy
-
-
- {
- const newModelType = e.target.value;
- if (newModelType === "root") {
- setPrevReference(reference.length ? reference : []);
- setReference([]);
- } else {
- setReference(
- prevReference.length ? prevReference : reference
- );
+ Root model
+
+ Child of
+
+
+ {modelType === "child" && (
+
+
+ {/* ---------- Configure Source & Destination ---------- */}
+
+
+
+
+ Configure Source
+
+
+
+ {isSchemaExists && (
+
+
+
+
+
+
+ Configure Destination
+
+
+
+ {isSchemaExists && (
+
+
+ handleChange("schema_name", value, setModel, false)
+ }
+ options={allSchemas.map((value) => ({ value }))}
+ showSearch
+ popupMatchSelectWidth={false}
+ loading={isLoadingSchemas}
+ notFoundContent={
+ isLoadingSchemas ? "Loading schemas..." : "No schemas found"
+ }
+ />
+
+ )}
+
+ {
+ const noSpacesValue = value.replace(/\s/g, "");
+ handleChange("table_name", noSpacesValue, setModel, false);
+ }}
+ disabled={isSchemaExists && !model.schema_name}
+ />
diff --git a/frontend/src/ide/editor/no-code-model/no-code-model.css b/frontend/src/ide/editor/no-code-model/no-code-model.css
index 677d255..0c710ea 100644
--- a/frontend/src/ide/editor/no-code-model/no-code-model.css
+++ b/frontend/src/ide/editor/no-code-model/no-code-model.css
@@ -121,10 +121,19 @@
.configure-tables .ant-space,
.configure-tables .ant-select,
+.configure-tables .ant-select-auto-complete,
.width-100-percent {
width: 100% !important;
}
+.configure-section-card {
+ margin-bottom: 12px;
+}
+
+.configure-section-card h4:first-child {
+ margin-top: 0;
+}
+
.search-icon {
margin-left: -3px;
margin-right: 12px;
@@ -681,7 +690,8 @@
justify-content: space-between;
align-items: center;
padding-block: 8px;
- overflow-x: auto;
+ flex-wrap: wrap;
+ gap: 8px;
}
.custom-pagination-container .custom-pagination .ant-pagination-options {
diff --git a/frontend/src/ide/editor/no-code-toolbar/no-code-toolbar.css b/frontend/src/ide/editor/no-code-toolbar/no-code-toolbar.css
index 90f0f05..d401063 100644
--- a/frontend/src/ide/editor/no-code-toolbar/no-code-toolbar.css
+++ b/frontend/src/ide/editor/no-code-toolbar/no-code-toolbar.css
@@ -9,9 +9,16 @@
flex: 1;
overflow: hidden;
scroll-behavior: smooth;
- padding: 12px 0px 8px;
+ padding: 6px 12px;
+ margin-bottom: 6px;
display: flex;
align-items: center;
+ background-color: var(--menu-items-bg);
+ border-radius: 6px;
+}
+
+.no-code-toolbar-content > .ant-space {
+ padding-top: 11px;
}
/* Hidden toolbar items (overflow) */
diff --git a/frontend/src/ide/explorer/explorer-component.jsx b/frontend/src/ide/explorer/explorer-component.jsx
index 83ef24a..a578fdc 100644
--- a/frontend/src/ide/explorer/explorer-component.jsx
+++ b/frontend/src/ide/explorer/explorer-component.jsx
@@ -82,6 +82,7 @@ const IdeExplorer = ({
} = useProjectStore();
const currentSchema = useProjectStore((state) => state.currentSchema);
const setCurrentSchema = useProjectStore((state) => state.setCurrentSchema);
+ const setSchemaList = useProjectStore((state) => state.setSchemaList);
// Reset currentSchema on unmount to prevent stale data
useEffect(() => {
@@ -308,6 +309,9 @@ const IdeExplorer = ({
setCurrentSchema("");
}
+ // Store plain schema list in shared store
+ setSchemaList(allSchemas);
+
const items = allSchemas.map((el) => ({
label: el,
key: el,
diff --git a/frontend/src/store/project-store.js b/frontend/src/store/project-store.js
index e99f8d6..67be3b8 100644
--- a/frontend/src/store/project-store.js
+++ b/frontend/src/store/project-store.js
@@ -9,6 +9,7 @@ const STORE_VARIABLES = {
projectId: "",
renamedModel: {},
currentSchema: "",
+ schemaList: [],
};
const useProjectStore = create(
@@ -71,6 +72,11 @@ const useProjectStore = create(
return { currentSchema: schema };
});
},
+ setSchemaList: (list) => {
+ setState(() => {
+ return { schemaList: list };
+ });
+ },
}),
{
name: "project-tab-storage",