Compare commits
No commits in common. "6fe0289b1a28c9d448e608183a9b4e0cb5435c23" and "77d729545f96a2f8e8e93a0d2543b2bc47ee1adc" have entirely different histories.
6fe0289b1a
...
77d729545f
47
src/App.jsx
47
src/App.jsx
|
|
@ -10,26 +10,22 @@ function App() {
|
||||||
const getInitialTab = () => {
|
const getInitialTab = () => {
|
||||||
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 === '/dataflow') return 'dataflow';
|
||||||
if (pathname === '/settings') return 'settings';
|
if (pathname === '/settings') return 'settings';
|
||||||
// Default to canvas/qubit_service
|
// Default to canvas/explorer
|
||||||
window.history.pushState(null, '', '/qubit_service');
|
window.history.pushState(null, '', '/explorer');
|
||||||
return 'canvas';
|
return 'canvas';
|
||||||
};
|
};
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(getInitialTab());
|
const [activeTab, setActiveTab] = useState(getInitialTab());
|
||||||
// Add state to track the current database for DataflowCanvas
|
|
||||||
const [currentDbSlug, setCurrentDbSlug] = useState(null);
|
|
||||||
// Add state to track if the current database has schemas
|
|
||||||
const [hasSchemas, setHasSchemas] = useState(true);
|
|
||||||
|
|
||||||
// Handle browser back/forward navigation
|
// Handle browser back/forward navigation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleLocationChange = () => {
|
const handleLocationChange = () => {
|
||||||
const pathname = window.location.pathname;
|
const pathname = window.location.pathname;
|
||||||
if (pathname === '/qubit_service') setActiveTab('canvas');
|
if (pathname === '/explorer') 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 === '/dataflow') setActiveTab('dataflow');
|
||||||
// Settings tab would be handled here too
|
// Settings tab would be handled here too
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -47,17 +43,10 @@ function App() {
|
||||||
setActiveTab('dataflow');
|
setActiveTab('dataflow');
|
||||||
|
|
||||||
// Update URL path
|
// Update URL path
|
||||||
window.history.pushState(null, '', '/data_mappings');
|
window.history.pushState(null, '', '/dataflow');
|
||||||
|
|
||||||
// Set the current database slug to force DataflowCanvas to re-render
|
// Log the database info (in a real app, you would use this to initialize the DataFlow view)
|
||||||
setCurrentDbSlug(event.detail.databaseSlug);
|
|
||||||
|
|
||||||
// Set whether this database has schemas
|
|
||||||
setHasSchemas(!event.detail.isEmpty);
|
|
||||||
|
|
||||||
// Log the database info
|
|
||||||
console.log('Viewing DataFlow for database:', event.detail);
|
console.log('Viewing DataFlow for database:', event.detail);
|
||||||
console.log('Database has schemas:', !event.detail.isEmpty);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handler for switching to any tab
|
// Handler for switching to any tab
|
||||||
|
|
@ -66,9 +55,9 @@ function App() {
|
||||||
setActiveTab(event.detail);
|
setActiveTab(event.detail);
|
||||||
|
|
||||||
// Update URL path based on the tab
|
// Update URL path based on the tab
|
||||||
let path = '/qubit_service';
|
let path = '/explorer';
|
||||||
if (event.detail === 'charts') path = '/charts';
|
if (event.detail === 'charts') path = '/charts';
|
||||||
if (event.detail === 'data_mappigs') path = '/data_mappings';
|
if (event.detail === 'dataflow') path = '/dataflow';
|
||||||
if (event.detail === 'settings') path = '/settings';
|
if (event.detail === 'settings') path = '/settings';
|
||||||
|
|
||||||
window.history.pushState(null, '', path);
|
window.history.pushState(null, '', path);
|
||||||
|
|
@ -128,7 +117,7 @@ function App() {
|
||||||
{/* Navigation */}
|
{/* Navigation */}
|
||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
||||||
href="/qubit_service"
|
href="/explorer"
|
||||||
style={{
|
style={{
|
||||||
marginRight: '25px',
|
marginRight: '25px',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
@ -144,10 +133,10 @@ function App() {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setActiveTab('canvas');
|
setActiveTab('canvas');
|
||||||
window.history.pushState(null, '', '/qubit_service');
|
window.history.pushState(null, '', '/explorer');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Overview
|
Data Explorer
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="/charts"
|
href="/charts"
|
||||||
|
|
@ -172,7 +161,7 @@ function App() {
|
||||||
Advanced Charts
|
Advanced Charts
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="/data_mappings"
|
href="/dataflow"
|
||||||
style={{
|
style={{
|
||||||
marginRight: '25px',
|
marginRight: '25px',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
@ -188,10 +177,10 @@ function App() {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setActiveTab('dataflow');
|
setActiveTab('dataflow');
|
||||||
window.history.pushState(null, '', '/data_mappings');
|
window.history.pushState(null, '', '/dataflow');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Data Mapping
|
Data Flow
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="/settings"
|
href="/settings"
|
||||||
|
|
@ -373,11 +362,7 @@ function App() {
|
||||||
|
|
||||||
{activeTab === 'dataflow' && (
|
{activeTab === 'dataflow' && (
|
||||||
<>
|
<>
|
||||||
<DataflowCanvas
|
<DataflowCanvas />
|
||||||
key={`dataflow-${currentDbSlug || 'default'}-${hasSchemas ? 'has-schemas' : 'no-schemas'}-${Date.now()}`}
|
|
||||||
dbSlug={currentDbSlug}
|
|
||||||
hasSchemas={hasSchemas}
|
|
||||||
/>
|
|
||||||
<div style={{
|
<div style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
bottom: '20px',
|
bottom: '20px',
|
||||||
|
|
|
||||||
|
|
@ -1,220 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { FaTimes, FaColumns, FaKey } from 'react-icons/fa';
|
|
||||||
|
|
||||||
const ColumnCreationPopup = ({ onClose, onCreateColumn, tableInfo }) => {
|
|
||||||
const [columnName, setColumnName] = useState('');
|
|
||||||
const [dataType, setDataType] = useState('TEXT');
|
|
||||||
const [description, setDescription] = useState('');
|
|
||||||
const [alias, setAlias] = useState('');
|
|
||||||
const [isKey, setIsKey] = useState(false);
|
|
||||||
|
|
||||||
const handleSubmit = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (columnName.trim() === '') return;
|
|
||||||
|
|
||||||
onCreateColumn({
|
|
||||||
name: columnName,
|
|
||||||
data_type: dataType,
|
|
||||||
description: description,
|
|
||||||
alias: alias,
|
|
||||||
is_key: isKey ? 1 : 0,
|
|
||||||
tbl: tableInfo.tbl,
|
|
||||||
sch: tableInfo.sch,
|
|
||||||
con: tableInfo.con
|
|
||||||
});
|
|
||||||
|
|
||||||
onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="popup-overlay" style={{
|
|
||||||
position: 'fixed',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
zIndex: 1000
|
|
||||||
}}>
|
|
||||||
<div className="popup-content" style={{
|
|
||||||
backgroundColor: 'white',
|
|
||||||
padding: '20px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
width: '500px',
|
|
||||||
maxWidth: '90%',
|
|
||||||
maxHeight: '90vh',
|
|
||||||
overflowY: 'auto',
|
|
||||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)'
|
|
||||||
}}>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px' }}>
|
|
||||||
<h2 style={{ margin: 0, display: 'flex', alignItems: 'center', gap: '10px', color: "black" }}>
|
|
||||||
<FaColumns />
|
|
||||||
Add New Column
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
background: 'none',
|
|
||||||
border: 'none',
|
|
||||||
fontSize: '20px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: '#999'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaTimes />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px', padding: '10px', backgroundColor: '#f5f5f5', borderRadius: '4px' }}>
|
|
||||||
<p style={{ margin: 0, color: '#333' }}>
|
|
||||||
<strong>Table:</strong> {tableInfo.tbl}
|
|
||||||
<br />
|
|
||||||
<strong>Schema:</strong> {tableInfo.sch}
|
|
||||||
<br />
|
|
||||||
<strong>Database:</strong> {tableInfo.con}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Column Name:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={columnName}
|
|
||||||
onChange={(e) => setColumnName(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9'
|
|
||||||
}}
|
|
||||||
placeholder="Enter column name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Data Type:
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
value={dataType}
|
|
||||||
onChange={(e) => setDataType(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<option value="TEXT">TEXT</option>
|
|
||||||
<option value="INTEGER">INTEGER</option>
|
|
||||||
<option value="FLOAT">FLOAT</option>
|
|
||||||
<option value="BOOLEAN">BOOLEAN</option>
|
|
||||||
<option value="DATE">DATE</option>
|
|
||||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
|
||||||
<option value="JSON">JSON</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Description:
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
value={description}
|
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
minHeight: '80px'
|
|
||||||
}}
|
|
||||||
placeholder="Enter column description"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Display Alias:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={alias}
|
|
||||||
onChange={(e) => setAlias(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9'
|
|
||||||
}}
|
|
||||||
placeholder="Enter display alias (optional)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '8px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: "black"
|
|
||||||
}}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={isKey}
|
|
||||||
onChange={(e) => setIsKey(e.target.checked)}
|
|
||||||
style={{ margin: 0 }}
|
|
||||||
/>
|
|
||||||
<FaKey style={{ color: isKey ? '#faad14' : '#d9d9d9' }} />
|
|
||||||
Is Key Column
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginTop: '20px' }}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: 'white',
|
|
||||||
color: '#333',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: '#1890ff',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaColumns size={14} />
|
|
||||||
Add Column
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ColumnCreationPopup;
|
|
||||||
|
|
@ -1,551 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { FaTimes, FaColumns, FaKey, FaPlus, FaEdit, FaTrash, FaSave, FaUndo } from 'react-icons/fa';
|
|
||||||
|
|
||||||
const ColumnManagementPopup = ({ onClose, onCreateColumn, onUpdateColumn, onDeleteColumn, tableInfo, existingColumns = [] }) => {
|
|
||||||
// State for the list of columns
|
|
||||||
const [columns, setColumns] = useState([]);
|
|
||||||
|
|
||||||
// State for the new column form
|
|
||||||
const [newColumn, setNewColumn] = useState({
|
|
||||||
name: '',
|
|
||||||
data_type: 'TEXT',
|
|
||||||
description: '',
|
|
||||||
alias: '',
|
|
||||||
is_key: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// State for tracking which column is being edited
|
|
||||||
const [editingColumnIndex, setEditingColumnIndex] = useState(null);
|
|
||||||
|
|
||||||
// State for the column being edited
|
|
||||||
const [editingColumn, setEditingColumn] = useState(null);
|
|
||||||
|
|
||||||
// Load existing columns when the component mounts
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('Existing columns received:', existingColumns);
|
|
||||||
|
|
||||||
if (existingColumns && existingColumns.length > 0) {
|
|
||||||
// Make sure each column has both slug and col properties
|
|
||||||
const processedColumns = existingColumns.map(column => {
|
|
||||||
// Ensure we have a valid column identifier
|
|
||||||
const colId = column.col || column.slug || column.id || column.column_id;
|
|
||||||
|
|
||||||
if (!colId) {
|
|
||||||
console.warn('Column without identifier:', column);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...column,
|
|
||||||
col: colId, // Ensure col exists
|
|
||||||
slug: colId // Ensure slug exists
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('Processed columns:', processedColumns);
|
|
||||||
setColumns(processedColumns);
|
|
||||||
} else {
|
|
||||||
console.log('No existing columns or empty array received');
|
|
||||||
setColumns([]);
|
|
||||||
}
|
|
||||||
}, [existingColumns]);
|
|
||||||
|
|
||||||
// Handle input change for the new column form
|
|
||||||
const handleNewColumnChange = (e) => {
|
|
||||||
const { name, value, type, checked } = e.target;
|
|
||||||
setNewColumn({
|
|
||||||
...newColumn,
|
|
||||||
[name]: type === 'checkbox' ? checked : value
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle input change for the editing column form
|
|
||||||
const handleEditColumnChange = (e) => {
|
|
||||||
const { name, value, type, checked } = e.target;
|
|
||||||
setEditingColumn({
|
|
||||||
...editingColumn,
|
|
||||||
[name]: type === 'checkbox' ? checked : value
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle adding a new column
|
|
||||||
const handleAddColumn = () => {
|
|
||||||
if (newColumn.name.trim() === '') return;
|
|
||||||
|
|
||||||
// Call the create column function
|
|
||||||
onCreateColumn({
|
|
||||||
name: newColumn.name,
|
|
||||||
data_type: newColumn.data_type,
|
|
||||||
description: newColumn.description,
|
|
||||||
alias: newColumn.alias,
|
|
||||||
is_key: newColumn.is_key ? 1 : 0,
|
|
||||||
tbl: tableInfo.tbl,
|
|
||||||
sch: tableInfo.sch,
|
|
||||||
con: tableInfo.con
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reset the form
|
|
||||||
setNewColumn({
|
|
||||||
name: '',
|
|
||||||
data_type: 'TEXT',
|
|
||||||
description: '',
|
|
||||||
alias: '',
|
|
||||||
is_key: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle editing a column
|
|
||||||
const handleEditColumn = (index) => {
|
|
||||||
setEditingColumnIndex(index);
|
|
||||||
setEditingColumn({ ...columns[index] });
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle saving an edited column
|
|
||||||
const handleSaveEdit = () => {
|
|
||||||
if (!editingColumn || editingColumn.name.trim() === '') return;
|
|
||||||
|
|
||||||
// Call the update column function
|
|
||||||
onUpdateColumn({
|
|
||||||
col: editingColumn.col || editingColumn.slug, // Use col if available, otherwise use slug
|
|
||||||
name: editingColumn.name,
|
|
||||||
data_type: editingColumn.data_type,
|
|
||||||
description: editingColumn.description,
|
|
||||||
alias: editingColumn.alias,
|
|
||||||
is_key: editingColumn.is_key ? 1 : 0,
|
|
||||||
tbl: tableInfo.tbl,
|
|
||||||
sch: tableInfo.sch,
|
|
||||||
con: tableInfo.con
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the columns array
|
|
||||||
const updatedColumns = [...columns];
|
|
||||||
updatedColumns[editingColumnIndex] = editingColumn;
|
|
||||||
setColumns(updatedColumns);
|
|
||||||
|
|
||||||
// Reset the editing state
|
|
||||||
setEditingColumnIndex(null);
|
|
||||||
setEditingColumn(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle canceling an edit
|
|
||||||
const handleCancelEdit = () => {
|
|
||||||
setEditingColumnIndex(null);
|
|
||||||
setEditingColumn(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle deleting a column
|
|
||||||
const handleDeleteColumn = (index) => {
|
|
||||||
const column = columns[index];
|
|
||||||
|
|
||||||
console.log('Attempting to delete column:', column);
|
|
||||||
console.log('Column properties:', {
|
|
||||||
name: column.name,
|
|
||||||
slug: column.slug,
|
|
||||||
col: column.col,
|
|
||||||
data_type: column.data_type
|
|
||||||
});
|
|
||||||
|
|
||||||
// Confirm deletion
|
|
||||||
if (window.confirm(`Are you sure you want to delete the column "${column.name}"?`)) {
|
|
||||||
// Create the payload with both col and slug for maximum compatibility
|
|
||||||
const payload = {
|
|
||||||
col: column.col || column.slug, // Use col if available, otherwise use slug
|
|
||||||
slug: column.slug || column.col, // Include slug as well
|
|
||||||
tbl: tableInfo.tbl,
|
|
||||||
sch: tableInfo.sch,
|
|
||||||
con: tableInfo.con,
|
|
||||||
name: column.name // Include name for logging
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Sending delete payload:', payload);
|
|
||||||
|
|
||||||
// Call the delete column function
|
|
||||||
onDeleteColumn(payload);
|
|
||||||
|
|
||||||
// Remove the column from the array
|
|
||||||
const updatedColumns = [...columns];
|
|
||||||
updatedColumns.splice(index, 1);
|
|
||||||
setColumns(updatedColumns);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="popup-overlay" style={{
|
|
||||||
position: 'fixed',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
zIndex: 1000
|
|
||||||
}}>
|
|
||||||
<div className="popup-content" style={{
|
|
||||||
backgroundColor: 'white',
|
|
||||||
padding: '20px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
width: '700px',
|
|
||||||
maxWidth: '90%',
|
|
||||||
maxHeight: '90vh',
|
|
||||||
overflowY: 'auto',
|
|
||||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)'
|
|
||||||
}}>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px' }}>
|
|
||||||
<h2 style={{ margin: 0, display: 'flex', alignItems: 'center', gap: '10px', color: "black" }}>
|
|
||||||
<FaColumns />
|
|
||||||
Manage Columns
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
background: 'none',
|
|
||||||
border: 'none',
|
|
||||||
fontSize: '20px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: '#999'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaTimes />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px', padding: '10px', backgroundColor: '#f5f5f5', borderRadius: '4px' }}>
|
|
||||||
<p style={{ margin: 0, color: '#333' }}>
|
|
||||||
<strong>Table:</strong> {tableInfo.tbl}
|
|
||||||
<br />
|
|
||||||
<strong>Schema:</strong> {tableInfo.sch}
|
|
||||||
<br />
|
|
||||||
<strong>Database:</strong> {tableInfo.con}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Existing Columns Section */}
|
|
||||||
<div style={{ marginBottom: '20px' }}>
|
|
||||||
<h3 style={{ color: 'black', borderBottom: '1px solid #eee', paddingBottom: '8px' }}>
|
|
||||||
Existing Columns
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{columns.length === 0 ? (
|
|
||||||
<div style={{ padding: '15px', textAlign: 'center', color: 'black', backgroundColor: '#f9f9f9', borderRadius: '4px' }}>
|
|
||||||
No columns found for this table.
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div style={{
|
|
||||||
border: '1px solid #eee',
|
|
||||||
borderRadius: '4px',
|
|
||||||
overflow: 'hidden'
|
|
||||||
}}>
|
|
||||||
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
|
|
||||||
<thead>
|
|
||||||
<tr style={{ backgroundColor: '#f5f5f5' }}>
|
|
||||||
<th style={{ padding: '10px', textAlign: 'left', borderBottom: '1px solid #eee', color: 'black', fontWeight: 'bold' }}>Name</th>
|
|
||||||
<th style={{ padding: '10px', textAlign: 'left', borderBottom: '1px solid #eee', color: 'black', fontWeight: 'bold' }}>Type</th>
|
|
||||||
<th style={{ padding: '10px', textAlign: 'left', borderBottom: '1px solid #eee', color: 'black', fontWeight: 'bold' }}>Key</th>
|
|
||||||
<th style={{ padding: '10px', textAlign: 'right', borderBottom: '1px solid #eee', color: 'black', fontWeight: 'bold' }}>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{columns.map((column, index) => (
|
|
||||||
<tr key={`column-${index}-${column.name}`} style={{ borderBottom: '1px solid #eee' }}>
|
|
||||||
{editingColumnIndex === index ? (
|
|
||||||
// Editing mode
|
|
||||||
<>
|
|
||||||
<td style={{ padding: '10px' }}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
value={editingColumn.name}
|
|
||||||
onChange={handleEditColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '6px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td style={{ padding: '10px' }}>
|
|
||||||
<select
|
|
||||||
name="data_type"
|
|
||||||
value={editingColumn.data_type}
|
|
||||||
onChange={handleEditColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '6px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<option value="TEXT" style={{ color: 'black' }}>TEXT</option>
|
|
||||||
<option value="INTEGER" style={{ color: 'black' }}>INTEGER</option>
|
|
||||||
<option value="FLOAT" style={{ color: 'black' }}>FLOAT</option>
|
|
||||||
<option value="BOOLEAN" style={{ color: 'black' }}>BOOLEAN</option>
|
|
||||||
<option value="DATE" style={{ color: 'black' }}>DATE</option>
|
|
||||||
<option value="TIMESTAMP" style={{ color: 'black' }}>TIMESTAMP</option>
|
|
||||||
<option value="JSON" style={{ color: 'black' }}>JSON</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td style={{ padding: '10px' }}>
|
|
||||||
<label style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="is_key"
|
|
||||||
checked={editingColumn.is_key}
|
|
||||||
onChange={handleEditColumnChange}
|
|
||||||
/>
|
|
||||||
<FaKey style={{ color: editingColumn.is_key ? '#faad14' : '#d9d9d9' }} />
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
<td style={{ padding: '10px', textAlign: 'right' }}>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '5px' }}>
|
|
||||||
<button
|
|
||||||
onClick={handleSaveEdit}
|
|
||||||
style={{
|
|
||||||
background: '#52c41a',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
padding: '5px 10px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaSave size={12} />
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleCancelEdit}
|
|
||||||
style={{
|
|
||||||
background: '#f5f5f5',
|
|
||||||
color: '#333',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
borderRadius: '4px',
|
|
||||||
padding: '5px 10px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaUndo size={12} />
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
// View mode
|
|
||||||
<>
|
|
||||||
<td style={{ padding: '10px', color: 'black' }}>{column.name}</td>
|
|
||||||
<td style={{ padding: '10px', color: 'black' }}>{column.data_type}</td>
|
|
||||||
<td style={{ padding: '10px', color: 'black' }}>
|
|
||||||
{column.is_key && <FaKey style={{ color: '#faad14' }} />}
|
|
||||||
</td>
|
|
||||||
<td style={{ padding: '10px', textAlign: 'right' }}>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '5px' }}>
|
|
||||||
<button
|
|
||||||
onClick={() => handleEditColumn(index)}
|
|
||||||
style={{
|
|
||||||
background: '#1890ff',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
padding: '5px 10px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaEdit size={12} />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => handleDeleteColumn(index)}
|
|
||||||
style={{
|
|
||||||
background: '#ff4d4f',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
padding: '5px 10px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaTrash size={12} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Add New Column Section */}
|
|
||||||
<div style={{ marginTop: '20px' }}>
|
|
||||||
<h3 style={{ color: 'black', borderBottom: '1px solid #eee', paddingBottom: '8px' }}>
|
|
||||||
Add New Column
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '15px', marginBottom: '15px' }}>
|
|
||||||
<div>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Column Name:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
value={newColumn.name}
|
|
||||||
onChange={handleNewColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter column name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Data Type:
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
name="data_type"
|
|
||||||
value={newColumn.data_type}
|
|
||||||
onChange={handleNewColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<option value="TEXT" style={{ color: 'black' }}>TEXT</option>
|
|
||||||
<option value="INTEGER" style={{ color: 'black' }}>INTEGER</option>
|
|
||||||
<option value="FLOAT" style={{ color: 'black' }}>FLOAT</option>
|
|
||||||
<option value="BOOLEAN" style={{ color: 'black' }}>BOOLEAN</option>
|
|
||||||
<option value="DATE" style={{ color: 'black' }}>DATE</option>
|
|
||||||
<option value="TIMESTAMP" style={{ color: 'black' }}>TIMESTAMP</option>
|
|
||||||
<option value="JSON" style={{ color: 'black' }}>JSON</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Description:
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
name="description"
|
|
||||||
value={newColumn.description}
|
|
||||||
onChange={handleNewColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
minHeight: '60px',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter column description"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: '15px', marginBottom: '15px', alignItems: 'end' }}>
|
|
||||||
<div>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
|
||||||
Display Alias:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="alias"
|
|
||||||
value={newColumn.alias}
|
|
||||||
onChange={handleNewColumnChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter display alias (optional)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '8px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: "black",
|
|
||||||
padding: '8px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
borderRadius: '4px',
|
|
||||||
backgroundColor: newColumn.is_key ? '#fffbe6' : 'transparent'
|
|
||||||
}}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="is_key"
|
|
||||||
checked={newColumn.is_key}
|
|
||||||
onChange={handleNewColumnChange}
|
|
||||||
style={{ margin: 0 }}
|
|
||||||
/>
|
|
||||||
<FaKey style={{ color: newColumn.is_key ? '#faad14' : '#d9d9d9' }} />
|
|
||||||
Is Key Column
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '20px' }}>
|
|
||||||
<button
|
|
||||||
onClick={handleAddColumn}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: '#1890ff',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaPlus size={14} />
|
|
||||||
Add Column
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginTop: '20px', borderTop: '1px solid #eee', paddingTop: '20px' }}>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: 'white',
|
|
||||||
color: '#333',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ColumnManagementPopup;
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1051,13 +1051,13 @@ const DatabaseNode = ({ data = {} }) => {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div style={{ fontSize: '0.8em', color: '#aaa', marginBottom: '5px' }}>
|
<div style={{ fontSize: '0.8em', color: '#aaa', marginBottom: '5px' }}>
|
||||||
{`${data.schemas} schemas • ${data.tables} tables`}
|
{`${data.schemas} schemas • ${data.tables} tables`}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ fontSize: '0.7em', color: '#888', marginBottom: '10px' }}>
|
<div style={{ fontSize: '0.7em', color: '#888', marginBottom: '10px' }}>
|
||||||
Connection: {dbSlug}
|
Connection: {dbSlug}
|
||||||
</div> */}
|
</div>
|
||||||
|
|
||||||
{/* View Details Button */}
|
{/* View Details Button */}
|
||||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||||
|
|
@ -1091,7 +1091,7 @@ const DatabaseNode = ({ data = {} }) => {
|
||||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M12 4.5C7 4.5 2.73 7.61 1 12C2.73 16.39 7 19.5 12 19.5C17 19.5 21.27 16.39 23 12C21.27 7.61 17 4.5 12 4.5ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z" fill="white"/>
|
<path d="M12 4.5C7 4.5 2.73 7.61 1 12C2.73 16.39 7 19.5 12 19.5C17 19.5 21.27 16.39 23 12C21.27 7.61 17 4.5 12 4.5ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z" fill="white"/>
|
||||||
</svg>
|
</svg>
|
||||||
View Data Mapping
|
View Data Flow
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1908,24 +1908,20 @@ const InfiniteCanvas = () => {
|
||||||
|
|
||||||
console.log(`Viewing data flow for database: ${dbName} (${dbSlug})`);
|
console.log(`Viewing data flow for database: ${dbName} (${dbSlug})`);
|
||||||
|
|
||||||
// Selectively clear cached data for the current database only
|
// Clear any existing schemas in localStorage for this database
|
||||||
try {
|
try {
|
||||||
// Only clear the cache for the current database
|
// Clear any existing schemas for this database
|
||||||
|
localStorage.removeItem(`schemas_${dbSlug}`);
|
||||||
|
localStorage.removeItem(`tables_${dbSlug}`);
|
||||||
|
|
||||||
|
// If this is "service 2" (my_dwh2), set empty schemas
|
||||||
if (dbSlug === 'my_dwh2') {
|
if (dbSlug === 'my_dwh2') {
|
||||||
console.log('Setting empty schemas for service 2 database');
|
console.log('Setting empty schemas for service 2 database');
|
||||||
// For service 2, we want to ensure it always shows as empty
|
|
||||||
localStorage.setItem(`schemas_${dbSlug}`, JSON.stringify([]));
|
localStorage.setItem(`schemas_${dbSlug}`, JSON.stringify([]));
|
||||||
localStorage.setItem(`tables_${dbSlug}`, JSON.stringify([]));
|
localStorage.setItem(`tables_${dbSlug}`, JSON.stringify([]));
|
||||||
} else {
|
|
||||||
// For other databases like MyDataWarehouseDB, we want to preserve their data
|
|
||||||
// but ensure we're not using stale data
|
|
||||||
console.log(`Preserving schemas for database: ${dbName}`);
|
|
||||||
|
|
||||||
// We don't need to clear anything for MyDataWarehouseDB
|
|
||||||
// This ensures its schemas will be loaded from the API or mock data
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error managing cached data in localStorage:', error);
|
console.error('Error clearing schemas from localStorage:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the selected database info in localStorage for the DataFlow component to use
|
// Store the selected database info in localStorage for the DataFlow component to use
|
||||||
|
|
@ -1933,34 +1929,23 @@ const InfiniteCanvas = () => {
|
||||||
id: dbId,
|
id: dbId,
|
||||||
name: dbName,
|
name: dbName,
|
||||||
slug: dbSlug, // Include the slug for API calls
|
slug: dbSlug, // Include the slug for API calls
|
||||||
isEmpty: dbSlug === 'my_dwh2', // Flag to indicate if this database has no schemas
|
isEmpty: dbSlug === 'my_dwh2' // Flag to indicate if this database has no schemas
|
||||||
timestamp: Date.now() // Add timestamp to ensure uniqueness
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Set the current database slug in mockData.js
|
// Set the current database slug in mockData.js
|
||||||
if (typeof window.setCurrentDbSlug === 'function') {
|
if (typeof window.setCurrentDbSlug === 'function') {
|
||||||
// First clear any existing data
|
window.setCurrentDbSlug(dbSlug);
|
||||||
window.setCurrentDbSlug(null);
|
|
||||||
|
|
||||||
// Then set the new database slug
|
|
||||||
setTimeout(() => {
|
|
||||||
window.setCurrentDbSlug(dbSlug);
|
|
||||||
}, 50);
|
|
||||||
} else {
|
} else {
|
||||||
console.warn('window.setCurrentDbSlug function is not available');
|
console.warn('window.setCurrentDbSlug function is not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this database should have empty schemas
|
|
||||||
const isEmpty = dbSlug === 'my_dwh2';
|
|
||||||
|
|
||||||
// Trigger an event that App.jsx can listen to
|
// Trigger an event that App.jsx can listen to
|
||||||
const event = new CustomEvent('viewDataFlow', {
|
const event = new CustomEvent('viewDataFlow', {
|
||||||
detail: {
|
detail: {
|
||||||
databaseId: dbId,
|
databaseId: dbId,
|
||||||
databaseName: dbName,
|
databaseName: dbName,
|
||||||
databaseSlug: dbSlug,
|
databaseSlug: dbSlug,
|
||||||
isEmpty: isEmpty, // Flag to indicate if this database has no schemas
|
isEmpty: dbSlug === 'my_dwh2' // Flag to indicate if this database has no schemas
|
||||||
timestamp: Date.now() // Add timestamp to ensure uniqueness
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
|
|
@ -2530,7 +2515,7 @@ const InfiniteCanvas = () => {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
}}
|
}}
|
||||||
title="Add DataSource"
|
title="Add Entity"
|
||||||
>
|
>
|
||||||
<svg width="99" height="36" viewBox="0 0 99 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="99" height="36" viewBox="0 0 99 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect x="0.5" y="0.5" width="98" height="35" rx="7.5" fill="#3EA29A"/>
|
<rect x="0.5" y="0.5" width="98" height="35" rx="7.5" fill="#3EA29A"/>
|
||||||
|
|
@ -2824,7 +2809,7 @@ const InfiniteCanvas = () => {
|
||||||
{/* Entity Creation Modal */}
|
{/* Entity Creation Modal */}
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={showAddEntityModal}
|
isOpen={showAddEntityModal}
|
||||||
title="Add DataSource"
|
title="Add Entity"
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setShowAddEntityModal(false);
|
setShowAddEntityModal(false);
|
||||||
setActiveEntityType('database');
|
setActiveEntityType('database');
|
||||||
|
|
|
||||||
|
|
@ -2,50 +2,19 @@ import React, { useState } from 'react';
|
||||||
import { FaPlus, FaTimes, FaTable, FaLayerGroup } from 'react-icons/fa';
|
import { FaPlus, FaTimes, FaTable, FaLayerGroup } from 'react-icons/fa';
|
||||||
import { CustomDatabaseIcon, CustomDocumentIcon, CustomDimensionIcon } from './CustomIcons';
|
import { CustomDatabaseIcon, CustomDocumentIcon, CustomDimensionIcon } from './CustomIcons';
|
||||||
|
|
||||||
// Add a style tag for animations
|
const TableCreationPopup = ({ onClose, onCreateTable }) => {
|
||||||
const styles = `
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; transform: translateY(-10px); }
|
|
||||||
to { opacity: 1; transform: translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from { opacity: 1; transform: translateY(0); }
|
|
||||||
to { opacity: 0; transform: translateY(-10px); }
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
|
||||||
const [tableName, setTableName] = useState('');
|
const [tableName, setTableName] = useState('');
|
||||||
const [externalName, setExternalName] = useState('');
|
|
||||||
const [tableType, setTableType] = useState('stage');
|
const [tableType, setTableType] = useState('stage');
|
||||||
const [description, setDescription] = useState('');
|
const [columns, setColumns] = useState([{ name: '', type: 'string' }]);
|
||||||
const [columns, setColumns] = useState([{ name: '', type: 'TEXT' }]);
|
|
||||||
const [newColumnName, setNewColumnName] = useState('');
|
const [newColumnName, setNewColumnName] = useState('');
|
||||||
const [newColumnType, setNewColumnType] = useState('TEXT');
|
const [newColumnType, setNewColumnType] = useState('string');
|
||||||
const [addSuccess, setAddSuccess] = useState(false); // To show success message
|
|
||||||
|
|
||||||
const handleAddColumn = () => {
|
const handleAddColumn = () => {
|
||||||
console.log('handleAddColumn called');
|
if (newColumnName.trim() === '') return;
|
||||||
if (newColumnName.trim() === '') {
|
|
||||||
console.log('Column name is empty, not adding');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Adding new column:', { name: newColumnName, type: newColumnType });
|
|
||||||
setColumns([...columns, { name: newColumnName, type: newColumnType }]);
|
setColumns([...columns, { name: newColumnName, type: newColumnType }]);
|
||||||
|
|
||||||
// Show success message
|
|
||||||
setAddSuccess(true);
|
|
||||||
|
|
||||||
// Clear the form
|
|
||||||
setNewColumnName('');
|
setNewColumnName('');
|
||||||
setNewColumnType('TEXT'); // Changed from 'string' to 'TEXT' to match our options
|
setNewColumnType('string');
|
||||||
|
|
||||||
// Hide success message after 2 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
setAddSuccess(false);
|
|
||||||
}, 2000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveColumn = (index) => {
|
const handleRemoveColumn = (index) => {
|
||||||
|
|
@ -64,15 +33,8 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
|
|
||||||
onCreateTable({
|
onCreateTable({
|
||||||
name: tableName,
|
name: tableName,
|
||||||
external_name: externalName || tableName,
|
type: tableType,
|
||||||
table_type: tableType,
|
columns: validColumns.map(col => col.name)
|
||||||
description: description,
|
|
||||||
sch: schemaInfo.sch,
|
|
||||||
con: schemaInfo.con,
|
|
||||||
columns: validColumns.map(col => ({
|
|
||||||
name: col.name,
|
|
||||||
data_type: col.type
|
|
||||||
}))
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onClose();
|
onClose();
|
||||||
|
|
@ -92,11 +54,7 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="popup-overlay" style={{
|
||||||
{/* Add the style tag for animations */}
|
|
||||||
<style dangerouslySetInnerHTML={{ __html: styles }} />
|
|
||||||
|
|
||||||
<div className="popup-overlay" style={{
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
|
|
@ -138,14 +96,6 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div style={{ marginBottom: '15px', padding: '10px', backgroundColor: '#f5f5f5', borderRadius: '4px' }}>
|
|
||||||
<p style={{ margin: 0, color: '#333' }}>
|
|
||||||
<strong>Schema:</strong> {schemaInfo?.sch}
|
|
||||||
<br />
|
|
||||||
<strong>Database:</strong> {schemaInfo?.con}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
<div style={{ marginBottom: '15px' }}>
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black"}}>
|
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black"}}>
|
||||||
Table Name:
|
Table Name:
|
||||||
|
|
@ -164,42 +114,6 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black"}}>
|
|
||||||
External Name (Optional):
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={externalName}
|
|
||||||
onChange={(e) => setExternalName(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9'
|
|
||||||
}}
|
|
||||||
placeholder="Enter external name"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black"}}>
|
|
||||||
Description:
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
value={description}
|
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
minHeight: '80px'
|
|
||||||
}}
|
|
||||||
placeholder="Enter table description"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
<div style={{ marginBottom: '15px' }}>
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "black" }}>
|
||||||
|
|
@ -332,13 +246,10 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
border: '1px solid #d9d9d9'
|
border: '1px solid #d9d9d9'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="TEXT">TEXT</option>
|
<option value="string">String</option>
|
||||||
<option value="INTEGER">INTEGER</option>
|
<option value="number">Number</option>
|
||||||
<option value="FLOAT">FLOAT</option>
|
<option value="date">Date</option>
|
||||||
<option value="BOOLEAN">BOOLEAN</option>
|
<option value="boolean">Boolean</option>
|
||||||
<option value="DATE">DATE</option>
|
|
||||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
|
||||||
<option value="JSON">JSON</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -370,38 +281,12 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ marginTop: '15px', marginBottom: '5px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', gap: '10px', alignItems: 'flex-end' }}>
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: "#333", fontSize: '14px' }}>
|
|
||||||
Add New Column:
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{/* Success message */}
|
|
||||||
{addSuccess && (
|
|
||||||
<div style={{
|
|
||||||
color: '#52c41a',
|
|
||||||
fontSize: '14px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px',
|
|
||||||
animation: 'fadeIn 0.3s ease-in-out'
|
|
||||||
}}>
|
|
||||||
<span style={{ fontSize: '16px' }}>✓</span> Column added!
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div style={{ display: 'flex', gap: '10px', alignItems: 'flex-end', marginBottom: '10px' }}>
|
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newColumnName}
|
value={newColumnName}
|
||||||
onChange={(e) => setNewColumnName(e.target.value)}
|
onChange={(e) => setNewColumnName(e.target.value)}
|
||||||
onKeyDown={(e) => {
|
|
||||||
// Add column when Enter key is pressed
|
|
||||||
if (e.key === 'Enter' && newColumnName.trim() !== '') {
|
|
||||||
e.preventDefault();
|
|
||||||
handleAddColumn();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
placeholder="New column name"
|
placeholder="New column name"
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
@ -422,45 +307,25 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
border: '1px solid #d9d9d9'
|
border: '1px solid #d9d9d9'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="TEXT">TEXT</option>
|
<option value="string">String</option>
|
||||||
<option value="INTEGER">INTEGER</option>
|
<option value="number">Number</option>
|
||||||
<option value="FLOAT">FLOAT</option>
|
<option value="date">Date</option>
|
||||||
<option value="BOOLEAN">BOOLEAN</option>
|
<option value="boolean">Boolean</option>
|
||||||
<option value="DATE">DATE</option>
|
|
||||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
|
||||||
<option value="JSON">JSON</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(e) => {
|
onClick={handleAddColumn}
|
||||||
e.preventDefault(); // Prevent form submission
|
|
||||||
console.log('Add button clicked');
|
|
||||||
handleAddColumn();
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
|
||||||
gap: '5px',
|
gap: '5px',
|
||||||
padding: '8px 12px',
|
padding: '8px 12px',
|
||||||
background: '#1890ff',
|
background: '#1890ff',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer'
|
||||||
minWidth: '80px',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
transition: 'all 0.2s ease',
|
|
||||||
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)'
|
|
||||||
}}
|
|
||||||
onMouseOver={(e) => {
|
|
||||||
e.currentTarget.style.background = '#096dd9';
|
|
||||||
e.currentTarget.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
|
|
||||||
}}
|
|
||||||
onMouseOut={(e) => {
|
|
||||||
e.currentTarget.style.background = '#1890ff';
|
|
||||||
e.currentTarget.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FaPlus size={12} />
|
<FaPlus size={12} />
|
||||||
|
|
@ -505,7 +370,6 @@ const TableCreationPopup = ({ onClose, onCreateTable, schemaInfo }) => {
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,286 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { FaTimes, FaTable, FaSave } from 'react-icons/fa';
|
|
||||||
import { CustomDatabaseIcon, CustomDocumentIcon, CustomDimensionIcon } from './CustomIcons';
|
|
||||||
|
|
||||||
const TableUpdatePopup = ({ onClose, onUpdateTable, tableInfo }) => {
|
|
||||||
const [tableName, setTableName] = useState('');
|
|
||||||
const [externalName, setExternalName] = useState('');
|
|
||||||
const [tableType, setTableType] = useState('stage');
|
|
||||||
const [description, setDescription] = useState('');
|
|
||||||
|
|
||||||
// Initialize form with table info
|
|
||||||
useEffect(() => {
|
|
||||||
if (tableInfo) {
|
|
||||||
setTableName(tableInfo.name || '');
|
|
||||||
setExternalName(tableInfo.external_name || '');
|
|
||||||
setTableType(tableInfo.table_type || 'stage');
|
|
||||||
setDescription(tableInfo.description || '');
|
|
||||||
}
|
|
||||||
}, [tableInfo]);
|
|
||||||
|
|
||||||
// Handle form submission
|
|
||||||
const handleSubmit = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Validate form
|
|
||||||
if (!tableName.trim()) {
|
|
||||||
alert('Table name is required');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the update table function
|
|
||||||
onUpdateTable({
|
|
||||||
tbl: tableInfo.tbl,
|
|
||||||
sch: tableInfo.sch,
|
|
||||||
con: tableInfo.con,
|
|
||||||
name: tableName,
|
|
||||||
external_name: externalName,
|
|
||||||
table_type: tableType,
|
|
||||||
description: description
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the appropriate icon based on table type
|
|
||||||
const getTableIcon = () => {
|
|
||||||
switch (tableType) {
|
|
||||||
case 'stage':
|
|
||||||
return <CustomDatabaseIcon width="16" height="16" />;
|
|
||||||
case 'dimension':
|
|
||||||
return <CustomDimensionIcon width="16" height="16" />;
|
|
||||||
case 'fact':
|
|
||||||
return <CustomDocumentIcon width="16" height="16" />;
|
|
||||||
default:
|
|
||||||
return <FaTable />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="popup-overlay" style={{
|
|
||||||
position: 'fixed',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
zIndex: 1000
|
|
||||||
}}>
|
|
||||||
<div className="popup-content" style={{
|
|
||||||
backgroundColor: 'white',
|
|
||||||
padding: '20px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
width: '500px',
|
|
||||||
maxWidth: '90%',
|
|
||||||
maxHeight: '90vh',
|
|
||||||
overflowY: 'auto',
|
|
||||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)'
|
|
||||||
}}>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px' }}>
|
|
||||||
<h2 style={{ margin: 0, display: 'flex', alignItems: 'center', gap: '10px', color: 'black' }}>
|
|
||||||
{getTableIcon()}
|
|
||||||
Update Table
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
background: 'none',
|
|
||||||
border: 'none',
|
|
||||||
fontSize: '20px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: '#999'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaTimes />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px', padding: '10px', backgroundColor: '#f5f5f5', borderRadius: '4px' }}>
|
|
||||||
<p style={{ margin: 0, color: '#333' }}>
|
|
||||||
<strong>Table:</strong> {tableInfo.tbl}
|
|
||||||
<br />
|
|
||||||
<strong>Schema:</strong> {tableInfo.sch}
|
|
||||||
<br />
|
|
||||||
<strong>Database:</strong> {tableInfo.con}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: 'black' }}>
|
|
||||||
Table Name:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={tableName}
|
|
||||||
onChange={(e) => setTableName(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter table name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: 'black' }}>
|
|
||||||
External Name:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={externalName}
|
|
||||||
onChange={(e) => setExternalName(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter external name (optional)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: 'black' }}>
|
|
||||||
Table Type:
|
|
||||||
</label>
|
|
||||||
<div style={{ display: 'flex', gap: '15px' }}>
|
|
||||||
<label style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
padding: '8px 12px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
backgroundColor: tableType === 'stage' ? 'rgba(250, 140, 22, 0.1)' : 'transparent',
|
|
||||||
borderColor: tableType === 'stage' ? '#fa8c16' : '#d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="tableType"
|
|
||||||
value="stage"
|
|
||||||
checked={tableType === 'stage'}
|
|
||||||
onChange={() => setTableType('stage')}
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
/>
|
|
||||||
<CustomDatabaseIcon width="16" height="16" style={{ marginRight: '5px' }} />
|
|
||||||
Stage
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
padding: '8px 12px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
backgroundColor: tableType === 'fact' ? 'rgba(24, 144, 255, 0.1)' : 'transparent',
|
|
||||||
borderColor: tableType === 'fact' ? '#1890ff' : '#d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="tableType"
|
|
||||||
value="fact"
|
|
||||||
checked={tableType === 'fact'}
|
|
||||||
onChange={() => setTableType('fact')}
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
/>
|
|
||||||
<CustomDocumentIcon width="16" height="16" style={{ marginRight: '5px' }} />
|
|
||||||
Fact
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
padding: '8px 12px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
backgroundColor: tableType === 'dimension' ? 'rgba(82, 196, 26, 0.1)' : 'transparent',
|
|
||||||
borderColor: tableType === 'dimension' ? '#52c41a' : '#d9d9d9',
|
|
||||||
color: 'black'
|
|
||||||
}}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="tableType"
|
|
||||||
value="dimension"
|
|
||||||
checked={tableType === 'dimension'}
|
|
||||||
onChange={() => setTableType('dimension')}
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
/>
|
|
||||||
<CustomDimensionIcon width="16" height="16" style={{ marginRight: '5px' }} />
|
|
||||||
Dimension
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '15px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold', color: 'black' }}>
|
|
||||||
Description:
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
value={description}
|
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
minHeight: '80px',
|
|
||||||
color: 'black'
|
|
||||||
}}
|
|
||||||
placeholder="Enter table description (optional)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginTop: '20px' }}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: 'white',
|
|
||||||
color: '#333',
|
|
||||||
border: '1px solid #d9d9d9',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
background: '#1890ff',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '5px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaSave size={14} />
|
|
||||||
Update Table
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TableUpdatePopup;
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue