Compare commits

..

No commits in common. "12165c703813807a60dc31f4ab47231d0077adb6" and "6fe0289b1a28c9d448e608183a9b4e0cb5435c23" have entirely different histories.

6 changed files with 204 additions and 520 deletions

View File

@ -394,84 +394,6 @@ main {
width: 80%; width: 80%;
} }
/* Secondary navigation bar styles */
.secondary-nav {
display: flex;
align-items: center;
padding: 10px 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
background: rgba(18, 18, 18, 0.8);
backdrop-filter: blur(10px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
position: relative;
}
/* Navigation button styles */
.nav-button {
display: flex;
align-items: center;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
margin-right: 8px;
user-select: none;
}
.nav-button:hover {
background: rgba(0, 169, 157, 0.1);
transform: translateY(-1px);
}
.nav-button.active {
background: rgba(0, 169, 157, 0.15);
border: 1px solid rgba(0, 169, 157, 0.3);
}
.nav-button.active span {
color: #fff;
font-weight: 500;
}
.nav-button svg {
margin-right: 8px;
}
/* User profile button styles */
.user-profile {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.05);
padding: 6px 12px;
border-radius: 20px;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.2s ease;
}
.user-profile:hover {
background: rgba(255, 255, 255, 0.1);
transform: translateY(-1px);
}
.notification-button {
width: 32px;
height: 32px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.2s ease;
}
.notification-button:hover {
background: rgba(255, 255, 255, 0.1);
transform: translateY(-1px);
}
/* Glow effect for active elements */ /* Glow effect for active elements */
.glow-effect { .glow-effect {
box-shadow: 0 0 15px rgba(82, 196, 26, 0.6); box-shadow: 0 0 15px rgba(82, 196, 26, 0.6);

View File

@ -3,7 +3,7 @@ import './App.css'
import InfiniteCanvas from './components/InfiniteCanvas' import InfiniteCanvas from './components/InfiniteCanvas'
import AdvancedCharts from './components/AdvancedCharts' import AdvancedCharts from './components/AdvancedCharts'
import DataflowCanvas from './components/DataflowCanvas' import DataflowCanvas from './components/DataflowCanvas'
import { FaDatabase, FaChartBar, FaProjectDiagram, FaSitemap, FaFolder, FaCog, FaChevronDown, FaChevronRight, FaTachometerAlt } from 'react-icons/fa' import { FaDatabase, FaChartBar, FaProjectDiagram } from 'react-icons/fa'
function App() { function App() {
// Initialize activeTab based on URL pathname if present // Initialize activeTab based on URL pathname if present
@ -11,7 +11,6 @@ function App() {
const pathname = window.location.pathname; const pathname = window.location.pathname;
if (pathname === '/charts') return 'charts'; if (pathname === '/charts') return 'charts';
if (pathname === '/data_mappings') return 'data_mappigs'; if (pathname === '/data_mappings') return 'data_mappigs';
if (pathname === '/er_diagram') return 'er_diagram';
if (pathname === '/settings') return 'settings'; if (pathname === '/settings') return 'settings';
// Default to canvas/qubit_service // Default to canvas/qubit_service
window.history.pushState(null, '', '/qubit_service'); window.history.pushState(null, '', '/qubit_service');
@ -23,8 +22,6 @@ function App() {
const [currentDbSlug, setCurrentDbSlug] = useState(null); const [currentDbSlug, setCurrentDbSlug] = useState(null);
// Add state to track if the current database has schemas // Add state to track if the current database has schemas
const [hasSchemas, setHasSchemas] = useState(true); const [hasSchemas, setHasSchemas] = useState(true);
// Add state to track whether the sidebar dropdown is open
const [isDropdownOpen, setIsDropdownOpen] = useState(true);
// Handle browser back/forward navigation // Handle browser back/forward navigation
useEffect(() => { useEffect(() => {
@ -33,7 +30,6 @@ function App() {
if (pathname === '/qubit_service') setActiveTab('canvas'); if (pathname === '/qubit_service') setActiveTab('canvas');
else if (pathname === '/charts') setActiveTab('charts'); else if (pathname === '/charts') setActiveTab('charts');
else if (pathname === '/data_mappings') setActiveTab('data_mappigs'); else if (pathname === '/data_mappings') setActiveTab('data_mappigs');
else if (pathname === '/er_diagram') setActiveTab('er_diagram');
// Settings tab would be handled here too // Settings tab would be handled here too
}; };
@ -73,7 +69,6 @@ function App() {
let path = '/qubit_service'; let path = '/qubit_service';
if (event.detail === 'charts') path = '/charts'; if (event.detail === 'charts') path = '/charts';
if (event.detail === 'data_mappigs') path = '/data_mappings'; if (event.detail === 'data_mappigs') path = '/data_mappings';
if (event.detail === 'er_diagram') path = '/er_diagram';
if (event.detail === 'settings') path = '/settings'; if (event.detail === 'settings') path = '/settings';
window.history.pushState(null, '', path); window.history.pushState(null, '', path);
@ -126,270 +121,202 @@ function App() {
WebkitTextFillColor: 'transparent', WebkitTextFillColor: 'transparent',
textShadow: '0 0 20px rgba(82, 196, 26, 0.3)' textShadow: '0 0 20px rgba(82, 196, 26, 0.3)'
}}> }}>
{/* The Metricverse The Metricverse
*/}
Qubit Service
</h1> </h1>
</div> </div>
{/* User profile and controls */} {/* Navigation */}
<div style={{ display: 'flex', alignItems: 'center' }}> <div>
<div className="user-profile"> <a
<svg href="/qubit_service"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
style={{ marginRight: '8px' }}
>
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
<span>John Doe</span>
</div>
<div className="notification-button">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
</svg>
</div>
</div>
</header>
<div style={{ flex: 1, display: 'flex', flexDirection: 'row', overflow: 'hidden' }}>
{/* Sidebar navigation with dropdown */}
<div className="sidebar-nav" style={{
width: '220px',
background: '#1a1a1a',
borderRight: '1px solid #333',
padding: '20px 0',
display: 'flex',
flexDirection: 'column'
}}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '5px', paddingLeft: '15px' }}>
{/* Main Qbit Item with Dropdown */}
<div
className="nav-button main-item"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
style={{ style={{
display: 'flex', marginRight: '25px',
alignItems: 'center',
padding: '12px 15px',
borderRadius: '6px',
cursor: 'pointer', cursor: 'pointer',
background: 'rgba(0, 169, 157, 0.15)', padding: '8px 12px',
transition: 'all 0.2s ease', borderRadius: '4px',
marginBottom: '5px' transition: 'all 0.3s ease',
position: 'relative',
background: activeTab === 'canvas' ? 'rgba(0, 169, 157, 0.2)' : 'transparent',
color: activeTab === 'canvas' ? '#00a99d' : '#ffffff',
textDecoration: 'none'
}} }}
> className="nav-item"
<FaFolder style={{ onClick={(e) => {
fontSize: '20px', e.preventDefault();
color: '#00a99d',
marginRight: '12px'
}} />
<span style={{
color: '#fff',
fontWeight: '600',
flex: 1
}}>
Qbit
</span>
{isDropdownOpen ?
<FaChevronDown style={{ color: '#aaa', fontSize: '14px' }} /> :
<FaChevronRight style={{ color: '#aaa', fontSize: '14px' }} />
}
</div>
{/* Dropdown items container with animation */}
<div
className="dropdown-container"
style={{
display: isDropdownOpen ? 'flex' : 'none',
flexDirection: 'column',
gap: '4px',
paddingLeft: '15px',
marginLeft: '10px',
borderLeft: '1px solid rgba(170, 170, 170, 0.2)',
transition: 'all 0.3s ease'
}}
>
{/* Overview Item */}
<div
className={`nav-button ${activeTab === 'canvas' ? 'active' : ''}`}
onClick={() => {
setActiveTab('canvas'); setActiveTab('canvas');
window.history.pushState(null, '', '/qubit_service'); window.history.pushState(null, '', '/qubit_service');
}} }}
style={{
display: 'flex',
alignItems: 'center',
padding: '8px 15px',
borderRadius: '6px',
cursor: 'pointer',
background: activeTab === 'canvas' ? 'rgba(0, 169, 157, 0.1)' : 'transparent',
transition: 'all 0.2s ease'
}}
> >
<FaProjectDiagram style={{
fontSize: '16px',
color: activeTab === 'canvas' ? '#00a99d' : '#aaa',
marginRight: '12px'
}} />
<span style={{
color: activeTab === 'canvas' ? '#fff' : '#aaa',
fontWeight: activeTab === 'canvas' ? '500' : 'normal'
}}>
Overview Overview
</span> </a>
</div> <a
href="/charts"
{/* ER Diagram Item */}
<div
className={`nav-button ${activeTab === 'er_diagram' ? 'active' : ''}`}
onClick={() => {
setActiveTab('er_diagram');
window.history.pushState(null, '', '/er_diagram');
}}
style={{ style={{
display: 'flex', marginRight: '25px',
alignItems: 'center',
padding: '8px 15px',
borderRadius: '6px',
cursor: 'pointer', cursor: 'pointer',
background: activeTab === 'er_diagram' ? 'rgba(0, 169, 157, 0.1)' : 'transparent', padding: '8px 12px',
transition: 'all 0.2s ease' borderRadius: '4px',
transition: 'all 0.3s ease',
position: 'relative',
background: activeTab === 'charts' ? 'rgba(0, 169, 157, 0.2)' : 'transparent',
color: activeTab === 'charts' ? '#00a99d' : '#ffffff',
textDecoration: 'none'
}} }}
> className="nav-item"
<FaSitemap style={{ onClick={(e) => {
fontSize: '16px', e.preventDefault();
color: activeTab === 'er_diagram' ? '#00a99d' : '#aaa',
marginRight: '12px'
}} />
<span style={{
color: activeTab === 'er_diagram' ? '#fff' : '#aaa',
fontWeight: activeTab === 'er_diagram' ? '500' : 'normal'
}}>
ER Diagram
</span>
</div>
{/* Data Mapping Item */}
<div
className={`nav-button ${activeTab === 'dataflow' ? 'active' : ''}`}
onClick={() => {
setActiveTab('dataflow');
window.history.pushState(null, '', '/data_mappings');
}}
style={{
display: 'flex',
alignItems: 'center',
padding: '8px 15px',
borderRadius: '6px',
cursor: 'pointer',
background: activeTab === 'dataflow' ? 'rgba(0, 169, 157, 0.1)' : 'transparent',
transition: 'all 0.2s ease'
}}
>
<FaDatabase style={{
fontSize: '16px',
color: activeTab === 'dataflow' ? '#00a99d' : '#aaa',
marginRight: '12px'
}} />
<span style={{
color: activeTab === 'dataflow' ? '#fff' : '#aaa',
fontWeight: activeTab === 'dataflow' ? '500' : 'normal'
}}>
Data Mapping
</span>
</div>
{/* Settings Item */}
<div
className={`nav-button ${activeTab === 'settings' ? 'active' : ''}`}
onClick={() => {
alert('Settings functionality not implemented yet');
}}
style={{
display: 'flex',
alignItems: 'center',
padding: '8px 15px',
borderRadius: '6px',
cursor: 'pointer',
background: activeTab === 'settings' ? 'rgba(0, 169, 157, 0.1)' : 'transparent',
transition: 'all 0.2s ease'
}}
>
<FaTachometerAlt
style={{
fontSize: '16px',
color: activeTab === 'settings' ? '#00a99d' : '#aaa',
marginRight: '12px'
}}
/>
<span style={{
color: activeTab === 'settings' ? '#fff' : '#aaa',
fontWeight: activeTab === 'settings' ? '500' : 'normal'
}}>
Dashboard
</span>
</div>
{/* Advanced Charts Item */}
{/* <div
className={`nav-button ${activeTab === 'charts' ? 'active' : ''}`}
onClick={() => {
setActiveTab('charts'); setActiveTab('charts');
window.history.pushState(null, '', '/charts'); window.history.pushState(null, '', '/charts');
}} }}
>
Advanced Charts
</a>
<a
href="/data_mappings"
style={{ style={{
display: 'flex', marginRight: '25px',
alignItems: 'center',
padding: '8px 15px',
borderRadius: '6px',
cursor: 'pointer', cursor: 'pointer',
background: activeTab === 'charts' ? 'rgba(0, 169, 157, 0.1)' : 'transparent', padding: '8px 12px',
transition: 'all 0.2s ease' borderRadius: '4px',
transition: 'all 0.3s ease',
position: 'relative',
background: activeTab === 'dataflow' ? 'rgba(0, 169, 157, 0.2)' : 'transparent',
color: activeTab === 'dataflow' ? '#00a99d' : '#ffffff',
textDecoration: 'none'
}}
className="nav-item"
onClick={(e) => {
e.preventDefault();
setActiveTab('dataflow');
window.history.pushState(null, '', '/data_mappings');
}} }}
> >
<FaChartBar style={{ Data Mapping
fontSize: '16px', </a>
color: activeTab === 'charts' ? '#00a99d' : '#aaa', <a
marginRight: '12px' href="/settings"
}} /> style={{
<span style={{ cursor: 'pointer',
color: activeTab === 'charts' ? '#fff' : '#aaa', padding: '8px 12px',
fontWeight: activeTab === 'charts' ? '500' : 'normal' borderRadius: '4px',
}}> transition: 'all 0.3s ease',
Advanced Charts
</span>
</div> */}
</div>
</div>
</div>
<main style={{
flex: 1,
overflow: 'hidden',
position: 'relative', position: 'relative',
padding: '20px' textDecoration: 'none',
color: '#ffffff'
}}
className="nav-item"
onClick={(e) => {
e.preventDefault();
// Settings functionality would go here
alert('Settings functionality not implemented yet');
}}
>
Settings
</a>
</div>
</header>
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
<aside>
<h3 style={{
color: '#52c41a',
marginBottom: '15px',
borderBottom: '1px solid #333',
paddingBottom: '10px',
fontSize: '1.1rem'
}}>Data Sources</h3>
<ul style={{ listStyle: 'none', padding: 0 }}>
<li style={{
padding: '10px',
cursor: 'pointer',
color: '#ffffff',
fontWeight: 'bold',
borderRadius: '6px',
background: 'rgba(0, 169, 157, 0.1)',
marginBottom: '8px',
border: '1px solid rgba(0, 169, 157, 0.3)',
transition: 'all 0.3s ease',
boxShadow: '0 0 10px rgba(0, 169, 157, 0.1)'
}} className="glow-effect">
<span style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: '24px',
height: '24px',
background: 'linear-gradient(45deg, #00a99d, #52c41a)',
borderRadius: '4px',
color: 'white',
marginRight: '10px',
fontSize: '12px'
}}> }}>
<FaDatabase />
</span>
Dbtez
</li>
</ul>
<h3 style={{
color: '#fa8c16',
marginTop: '25px',
marginBottom: '15px',
borderBottom: '1px solid #333',
paddingBottom: '10px',
fontSize: '1.1rem'
}}>Saved Views</h3>
<ul style={{ listStyle: 'none', padding: 0 }}>
<li style={{
padding: '10px',
cursor: 'pointer',
borderRadius: '6px',
transition: 'all 0.3s ease',
marginBottom: '8px',
background: 'rgba(255, 255, 255, 0.03)'
}}>
<span style={{
color: '#fa8c16',
marginRight: '8px',
fontSize: '16px'
}}>📊</span>
Sales Overview
</li>
<li style={{
padding: '10px',
cursor: 'pointer',
borderRadius: '6px',
transition: 'all 0.3s ease',
marginBottom: '8px',
background: 'rgba(255, 255, 255, 0.03)'
}}>
<span style={{
color: '#fa8c16',
marginRight: '8px',
fontSize: '16px'
}}>📊</span>
Marketing Performance
</li>
<li style={{
padding: '10px',
cursor: 'pointer',
borderRadius: '6px',
transition: 'all 0.3s ease',
background: 'rgba(255, 255, 255, 0.03)'
}}>
<span
style={{
color: '#fa8c16',
marginRight: '8px',
fontSize: '16px'
}}
>📊</span>
Financial Summary
</li>
</ul>
</aside>
<main style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
{activeTab === 'canvas' && ( {activeTab === 'canvas' && (
<> <>
<InfiniteCanvas /> <InfiniteCanvas />
@ -440,7 +367,7 @@ function App() {
{activeTab === 'charts' && ( {activeTab === 'charts' && (
<div style={{ padding: '20px', height: '100%', overflow: 'auto' }}> <div style={{ padding: '20px', height: '100%', overflow: 'auto' }}>
{/* <AdvancedCharts /> */} <AdvancedCharts />
</div> </div>
)} )}
@ -494,58 +421,6 @@ function App() {
</div> </div>
</> </>
)} )}
{activeTab === 'er_diagram' && (
<>
<DataflowCanvas
key={`er-diagram-${currentDbSlug || 'default'}-${hasSchemas ? 'has-schemas' : 'no-schemas'}-${Date.now()}`}
dbSlug={currentDbSlug}
hasSchemas={hasSchemas}
mode="er_diagram"
/>
<div style={{
position: 'absolute',
bottom: '20px',
left: '20px',
background: 'rgba(26, 26, 26, 0.8)',
padding: '12px 16px',
borderRadius: '8px',
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
fontSize: '12px',
pointerEvents: 'none',
backdropFilter: 'blur(5px)',
border: '1px solid rgba(138, 43, 226, 0.3)',
color: '#ffffff',
maxWidth: '300px',
animation: 'fadeIn 0.5s ease'
}}>
<p style={{
margin: 0,
display: 'flex',
alignItems: 'center',
fontSize: '13px'
}}>
<span style={{
display: 'inline-block',
width: '8px',
height: '8px',
background: '#8a2be2',
borderRadius: '50%',
marginRight: '8px',
boxShadow: '0 0 8px #8a2be2'
}}></span>
Entity Relationship Diagram
</p>
<p style={{
margin: '5px 0 0 16px',
fontSize: '11px',
opacity: 0.7
}}>
View table relationships Explore schema structure Analyze foreign keys
</p>
</div>
</>
)}
</main> </main>
</div> </div>
</div> </div>

View File

@ -1802,29 +1802,9 @@ const DataflowCanvas = ({ dbSlug, hasSchemas = true }) => {
type: table.type, type: table.type,
columns: table.columns, columns: table.columns,
slug: table.slug, slug: table.slug,
schema: table.schema, // Include schema information schema: table.schema // Include schema information
database: dbSlug // Include database information
}, },
position: (table.config && table.config.orientation) ? table.config.orientation : position: { x: table.orientation.x, y: table.orientation.y },
(table.orientation || {
// Try to get stored position from localStorage
...((() => {
try {
const storageKey = `table_position_${dbSlug}_${table.schema}_${table.slug}`;
const storedPosition = localStorage.getItem(storageKey);
if (storedPosition) {
return JSON.parse(storedPosition);
}
} catch (e) {
console.error('Error retrieving stored position:', e);
}
// Default random position if nothing is stored
return {
x: Math.floor(Math.random() * 700) + 100,
y: Math.floor(Math.random() * 700) + 100
};
})())
}),
parentNode: `schema-bg-${table.schema}`, // Connect to parent schema parentNode: `schema-bg-${table.schema}`, // Connect to parent schema
extent: 'parent', // Keep within parent boundaries extent: 'parent', // Keep within parent boundaries
style: { style: {
@ -2450,27 +2430,14 @@ const DataflowCanvas = ({ dbSlug, hasSchemas = true }) => {
try { try {
console.log('Creating new table with data:', tableData); console.log('Creating new table with data:', tableData);
// Extract orientation from config or use orientation directly, or generate random one // Call the createTable function with the provided data
const orientation = (tableData.config && tableData.config.orientation) ?
tableData.config.orientation :
(tableData.orientation || {
x: Math.floor(Math.random() * 700) + 100,
y: Math.floor(Math.random() * 700) + 100
});
console.log('Using orientation for new table:', orientation);
console.log('Using orientation for new table:', orientation);
// Call the createTable function with the provided data and orientation
const newTable = await createTable( const newTable = await createTable(
tableData.sch, tableData.sch,
tableData.name, tableData.name,
tableData.table_type, tableData.table_type,
tableData.external_name, tableData.external_name,
tableData.description, tableData.description,
tableData.con, tableData.con
orientation
); );
console.log('Table created successfully:', newTable); console.log('Table created successfully:', newTable);
@ -2493,10 +2460,10 @@ const DataflowCanvas = ({ dbSlug, hasSchemas = true }) => {
columns: columnNames, // Use the column names from the tableData columns: columnNames, // Use the column names from the tableData
columnDetails: tableData.columns || [] // Store the full column details columnDetails: tableData.columns || [] // Store the full column details
}, },
// Position the table inside the schema using the orientation from the API // Position the table inside the schema
position: newTable.orientation || { position: {
x: Math.floor(Math.random() * 400) + 100, x: Math.random() * 300 + 100,
y: Math.floor(Math.random() * 400) + 100 y: Math.random() * 300 + 100
}, },
// Make it part of the schema // Make it part of the schema
parentNode: `schema-${tableData.sch}`, parentNode: `schema-${tableData.sch}`,
@ -3300,46 +3267,6 @@ const DataflowCanvas = ({ dbSlug, hasSchemas = true }) => {
onInit={onInit} onInit={onInit}
onNodeClick={onNodeClick} onNodeClick={onNodeClick}
onMove={onMove} onMove={onMove}
onNodeDragStop={(event, node) => {
// Only handle table node drag events
if (node.type === 'table' && node.data) {
console.log('Table dragged to new position:', node.position);
console.log('Table data:', node.data);
// Send the new position to the API
if (node.data.slug && node.data.schema) {
try {
console.log('Updating table position through qbt_table_update endpoint');
// Prepare table data for update with config structure
const tableData = {
tbl: node.data.slug,
sch: node.data.schema,
con: node.data.database || dbSlug, // Use node's database or current dbSlug
name: node.data.label,
table_type: node.data.type || 'stage', // Default to stage if not specified
// Use config object with orientation nested inside
config: {
orientation: node.position
}
};
// Call the regular updateTable function
updateTable(tableData)
.then(result => {
console.log('Table position updated successfully through regular update:', result);
})
.catch(error => {
console.error('Failed to update table position:', error);
});
} catch (error) {
console.error('Error preparing table update:', error);
}
} else {
console.error('Missing data for table position update:', node.data);
}
}
}}
nodeTypes={nodeTypes} nodeTypes={nodeTypes}
edgeTypes={edgeTypes} edgeTypes={edgeTypes}
minZoom={0.05} minZoom={0.05}

View File

@ -1965,7 +1965,8 @@ const InfiniteCanvas = () => {
}); });
window.dispatchEvent(event); window.dispatchEvent(event);
// No alert needed for MVP - the view will change automatically // Alert the user about the redirection (in a real app, this would be a smooth transition)
alert(`Redirecting to Data Flow view for database: ${dbName}`);
}; };
// Initialize with database nodes from state instead of mockData // Initialize with database nodes from state instead of mockData

View File

@ -62,12 +62,6 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
// Filter out empty columns // Filter out empty columns
const validColumns = columns.filter(col => col.name.trim() !== ''); const validColumns = columns.filter(col => col.name.trim() !== '');
// Generate random position for the table within the schema
const randomOrientation = {
x: Math.floor(Math.random() * 400) + 100,
y: Math.floor(Math.random() * 400) + 100
};
onCreateTable({ onCreateTable({
name: tableName, name: tableName,
external_name: externalName || tableName, external_name: externalName || tableName,
@ -75,10 +69,6 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
description: description, description: description,
sch: schemaInfo.sch, sch: schemaInfo.sch,
con: schemaInfo.con, con: schemaInfo.con,
// Use config object with orientation nested inside (new API structure)
config: {
orientation: randomOrientation
},
columns: validColumns.map(col => ({ columns: validColumns.map(col => ({
name: col.name, name: col.name,
data_type: col.type data_type: col.type

View File

@ -1489,7 +1489,7 @@ export const useApiData = (forceRefresh = false, dbSlug = null) => {
fetchAndCacheAllData(true); fetchAndCacheAllData(true);
// Function to create a new table in a schema // Function to create a new table in a schema
const createTable = async (schemaSlug, tableName, tableType, externalName = "", description = "", dbSlug = null, orientation = null) => { const createTable = async (schemaSlug, tableName, tableType, externalName = "", description = "", dbSlug = null) => {
try { try {
// Use the provided dbSlug or fall back to the global currentDbSlug // Use the provided dbSlug or fall back to the global currentDbSlug
const databaseSlug = dbSlug || currentDbSlug; const databaseSlug = dbSlug || currentDbSlug;
@ -1513,12 +1513,6 @@ const createTable = async (schemaSlug, tableName, tableType, externalName = "",
console.log(`Creating new table "${tableName}" in schema: ${schemaSlug}, database: ${databaseSlug}`); console.log(`Creating new table "${tableName}" in schema: ${schemaSlug}, database: ${databaseSlug}`);
// Generate random position if not provided
const tableOrientation = orientation || {
x: Math.floor(Math.random() * 400) + 100,
y: Math.floor(Math.random() * 400) + 100
};
// Prepare the payload // Prepare the payload
const payload = { const payload = {
token: token, token: token,
@ -1528,8 +1522,7 @@ const createTable = async (schemaSlug, tableName, tableType, externalName = "",
name: tableName, name: tableName,
external_name: externalName || tableName, external_name: externalName || tableName,
table_type: tableType, table_type: tableType,
description: description, description: description
config: { orientation: tableOrientation }
}; };
console.log('Table create request payload:', payload); console.log('Table create request payload:', payload);
@ -1564,9 +1557,7 @@ const createTable = async (schemaSlug, tableName, tableType, externalName = "",
created_at: new Date().toISOString(), created_at: new Date().toISOString(),
schema: schemaSlug, schema: schemaSlug,
database: databaseSlug, database: databaseSlug,
columns: [], columns: []
orientation: tableOrientation, // Add orientation from the config
config: { orientation: tableOrientation } // Also include full config
}; };
return newTable; return newTable;
@ -1598,10 +1589,6 @@ const createTable = async (schemaSlug, tableName, tableType, externalName = "",
} }
}; };
// Note: We've removed the separate updateTablePosition function
// as we're now using the regular updateTable function to update positions
// This ensures the standard API endpoint (qbt_table_update) is used for all table updates
// Function to update a table // Function to update a table
const updateTable = async (tableData) => { const updateTable = async (tableData) => {
try { try {
@ -1614,7 +1601,7 @@ const updateTable = async (tableData) => {
console.log(`Using current database slug: ${currentDbSlug}`); console.log(`Using current database slug: ${currentDbSlug}`);
} }
const { tbl, sch, con, name, external_name, table_type, description, orientation } = tableData; const { tbl, sch, con, name, external_name, table_type, description } = tableData;
if (!con) { if (!con) {
console.error('Missing database identifier in tableData:', tableData); console.error('Missing database identifier in tableData:', tableData);
@ -1644,9 +1631,6 @@ const updateTable = async (tableData) => {
console.log(`Updating table "${name}" (${tbl}) in schema: ${sch}, database: ${con}`); console.log(`Updating table "${name}" (${tbl}) in schema: ${sch}, database: ${con}`);
// Prepare the payload // Prepare the payload
// Log orientation data
console.log('Table update orientation data:', orientation);
const payload = { const payload = {
token: token, token: token,
org: orgSlug, org: orgSlug,
@ -1656,13 +1640,7 @@ const updateTable = async (tableData) => {
name: name, name: name,
external_name: external_name || name, external_name: external_name || name,
table_type: table_type, table_type: table_type,
description: description || '', description: description || ''
config: {
orientation: orientation || tableData.orientation || {
x: Math.floor(Math.random() * 700) + 100,
y: Math.floor(Math.random() * 700) + 100
}
}
}; };
console.log('Table update request payload:', payload); console.log('Table update request payload:', payload);
@ -1684,11 +1662,6 @@ const updateTable = async (tableData) => {
if (response.data && response.data.success) { if (response.data && response.data.success) {
console.log(`Successfully updated table "${name}" in schema ${sch}`); console.log(`Successfully updated table "${name}" in schema ${sch}`);
// Extract orientation from config if available
const tableOrientation = orientation ||
(tableData.orientation ? tableData.orientation : null) ||
(payload.config && payload.config.orientation ? payload.config.orientation : null);
// Return the updated table object // Return the updated table object
const updatedTable = { const updatedTable = {
name: name, name: name,
@ -1697,13 +1670,9 @@ const updateTable = async (tableData) => {
description: description || '', description: description || '',
slug: tbl, slug: tbl,
schema: sch, schema: sch,
database: con, database: con
orientation: tableOrientation, // Include orientation from config in the response
config: payload.config // Also include the full config
}; };
console.log('Returning updated table with orientation:', updatedTable.orientation);
return updatedTable; return updatedTable;
} else { } else {
// If the API indicates failure // If the API indicates failure