Initial commit
This commit is contained in:
68
application/view/table/add_column.php
Normal file
68
application/view/table/add_column.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<div class="dbm-content-header">
|
||||
<div class="dbm-breadcrumb">
|
||||
<a href="<?php echo Config::get('URL'); ?>database/index">Databases</a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>database/show/<?php echo urlencode($this->database_name); ?>"><?php echo htmlspecialchars($this->database_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/structure/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>"><?php echo htmlspecialchars($this->table_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<span>Add Column</span>
|
||||
</div>
|
||||
<div class="dbm-title">
|
||||
<h1>Add Column</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dbm-content-body">
|
||||
<div class="dbm-card" style="max-width: 500px;">
|
||||
<div class="dbm-card-body">
|
||||
<form method="post" action="<?php echo Config::get('URL'); ?>table/addColumn/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>">
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Column Name</label>
|
||||
<input type="text" name="column_name" class="dbm-form-input" required pattern="[a-zA-Z0-9_]+" placeholder="column_name" style="width: 100%; max-width: 100%;">
|
||||
</div>
|
||||
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Type</label>
|
||||
<select name="column_type" class="dbm-form-select" style="width: 100%; max-width: 100%;">
|
||||
<option value="INT">INT</option>
|
||||
<option value="VARCHAR(255)">VARCHAR(255)</option>
|
||||
<option value="TEXT">TEXT</option>
|
||||
<option value="DATETIME">DATETIME</option>
|
||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
||||
<option value="DECIMAL(10,2)">DECIMAL(10,2)</option>
|
||||
<option value="BOOLEAN">BOOLEAN</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Null</label>
|
||||
<select name="column_null" class="dbm-form-select" style="width: 100%; max-width: 100%;">
|
||||
<option value="YES">NULL</option>
|
||||
<option value="NO">NOT NULL</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Default Value</label>
|
||||
<input type="text" name="column_default" class="dbm-form-input" placeholder="Leave empty for none" style="width: 100%; max-width: 100%;">
|
||||
</div>
|
||||
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Extra</label>
|
||||
<select name="column_extra" class="dbm-form-select" style="width: 100%; max-width: 100%;">
|
||||
<option value="">None</option>
|
||||
<option value="auto_increment">AUTO_INCREMENT</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="column_key" value="">
|
||||
|
||||
<div style="margin-top: 24px; display: flex; gap: 10px;">
|
||||
<button type="submit" name="submit_add_column" class="dbm-btn dbm-btn-success">Add Column</button>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/structure/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>" class="dbm-btn dbm-btn-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
122
application/view/table/create.php
Normal file
122
application/view/table/create.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<div class="dbm-content-header">
|
||||
<div class="dbm-breadcrumb">
|
||||
<a href="<?php echo Config::get('URL'); ?>database/index">Databases</a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>database/show/<?php echo urlencode($this->database_name); ?>"><?php echo htmlspecialchars($this->database_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<span>New Table</span>
|
||||
</div>
|
||||
<div class="dbm-title">
|
||||
<h1>Create New Table</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dbm-content-body">
|
||||
<div class="dbm-card">
|
||||
<div class="dbm-card-body">
|
||||
<form method="post" action="<?php echo Config::get('URL'); ?>table/create/<?php echo urlencode($this->database_name); ?>" id="create-table-form">
|
||||
<div class="dbm-form-group">
|
||||
<label class="dbm-form-label">Table Name</label>
|
||||
<input type="text" name="table_name" class="dbm-form-input" required pattern="[a-zA-Z0-9_]+" placeholder="my_table">
|
||||
</div>
|
||||
|
||||
<h3 style="color: var(--text-primary); margin: 24px 0 16px;">Columns</h3>
|
||||
|
||||
<div id="columns-container">
|
||||
<div class="column-row" style="display: flex; gap: 10px; margin-bottom: 12px; padding: 16px; background: var(--bg-input); border-radius: var(--radius); flex-wrap: wrap; align-items: center;">
|
||||
<input type="text" name="columns[0][name]" class="dbm-form-input" placeholder="Column name" required style="width: 150px; max-width: 150px;">
|
||||
<select name="columns[0][type]" class="dbm-form-select" style="width: 140px; max-width: 140px;">
|
||||
<option value="INT">INT</option>
|
||||
<option value="VARCHAR(255)">VARCHAR(255)</option>
|
||||
<option value="TEXT">TEXT</option>
|
||||
<option value="DATETIME">DATETIME</option>
|
||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
||||
<option value="DECIMAL(10,2)">DECIMAL(10,2)</option>
|
||||
<option value="BOOLEAN">BOOLEAN</option>
|
||||
</select>
|
||||
<select name="columns[0][null]" class="dbm-form-select" style="width: 100px; max-width: 100px;">
|
||||
<option value="YES">NULL</option>
|
||||
<option value="NO">NOT NULL</option>
|
||||
</select>
|
||||
<select name="columns[0][key]" class="dbm-form-select" style="width: 130px; max-width: 130px;">
|
||||
<option value="">No Key</option>
|
||||
<option value="PRI">PRIMARY KEY</option>
|
||||
</select>
|
||||
<input type="text" name="columns[0][default]" class="dbm-form-input" placeholder="Default" style="width: 100px; max-width: 100px;">
|
||||
<select name="columns[0][extra]" class="dbm-form-select" style="width: 140px; max-width: 140px;">
|
||||
<option value="">None</option>
|
||||
<option value="auto_increment">AUTO_INCREMENT</option>
|
||||
</select>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-danger remove-column" style="display: none;">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="add-column" class="dbm-btn dbm-btn-secondary" style="margin-top: 8px;">
|
||||
<i data-lucide="plus"></i>
|
||||
Add Column
|
||||
</button>
|
||||
|
||||
<div style="margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--border-color);">
|
||||
<button type="submit" name="submit_create_table" class="dbm-btn dbm-btn-success">
|
||||
<i data-lucide="check-circle"></i>
|
||||
Create Table
|
||||
</button>
|
||||
<a href="<?php echo Config::get('URL'); ?>database/show/<?php echo urlencode($this->database_name); ?>" class="dbm-btn dbm-btn-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let columnIndex = 1;
|
||||
|
||||
document.getElementById('add-column').addEventListener('click', function() {
|
||||
const container = document.getElementById('columns-container');
|
||||
const newRow = document.createElement('div');
|
||||
newRow.className = 'column-row';
|
||||
newRow.style.cssText = 'display: flex; gap: 10px; margin-bottom: 12px; padding: 16px; background: var(--bg-input); border-radius: var(--radius); flex-wrap: wrap; align-items: center;';
|
||||
newRow.innerHTML = `
|
||||
<input type="text" name="columns[${columnIndex}][name]" class="dbm-form-input" placeholder="Column name" required style="width: 150px; max-width: 150px;">
|
||||
<select name="columns[${columnIndex}][type]" class="dbm-form-select" style="width: 140px; max-width: 140px;">
|
||||
<option value="INT">INT</option>
|
||||
<option value="VARCHAR(255)">VARCHAR(255)</option>
|
||||
<option value="TEXT">TEXT</option>
|
||||
<option value="DATETIME">DATETIME</option>
|
||||
<option value="TIMESTAMP">TIMESTAMP</option>
|
||||
<option value="DECIMAL(10,2)">DECIMAL(10,2)</option>
|
||||
<option value="BOOLEAN">BOOLEAN</option>
|
||||
</select>
|
||||
<select name="columns[${columnIndex}][null]" class="dbm-form-select" style="width: 100px; max-width: 100px;">
|
||||
<option value="YES">NULL</option>
|
||||
<option value="NO">NOT NULL</option>
|
||||
</select>
|
||||
<select name="columns[${columnIndex}][key]" class="dbm-form-select" style="width: 130px; max-width: 130px;">
|
||||
<option value="">No Key</option>
|
||||
<option value="PRI">PRIMARY KEY</option>
|
||||
</select>
|
||||
<input type="text" name="columns[${columnIndex}][default]" class="dbm-form-input" placeholder="Default" style="width: 100px; max-width: 100px;">
|
||||
<select name="columns[${columnIndex}][extra]" class="dbm-form-select" style="width: 140px; max-width: 140px;">
|
||||
<option value="">None</option>
|
||||
<option value="auto_increment">AUTO_INCREMENT</option>
|
||||
</select>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-danger remove-column">Remove</button>
|
||||
`;
|
||||
container.appendChild(newRow);
|
||||
columnIndex++;
|
||||
|
||||
document.querySelectorAll('.remove-column').forEach(btn => btn.style.display = 'inline-flex');
|
||||
});
|
||||
|
||||
document.getElementById('columns-container').addEventListener('click', function(e) {
|
||||
if (e.target.classList.contains('remove-column')) {
|
||||
e.target.closest('.column-row').remove();
|
||||
const rows = document.querySelectorAll('.column-row');
|
||||
if (rows.length === 1) {
|
||||
rows[0].querySelector('.remove-column').style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
435
application/view/table/show.php
Normal file
435
application/view/table/show.php
Normal file
@@ -0,0 +1,435 @@
|
||||
<?php
|
||||
$total_pages = ceil($this->total_rows / $this->per_page);
|
||||
$pk_column = null;
|
||||
foreach ($this->columns as $col) {
|
||||
if ($col['Key'] === 'PRI') {
|
||||
$pk_column = $col['Field'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="dbm-content-header">
|
||||
<div class="dbm-breadcrumb">
|
||||
<a href="<?php echo Config::get('URL'); ?>database/index">Databases</a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>database/show/<?php echo urlencode($this->database_name); ?>"><?php echo htmlspecialchars($this->database_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<span><?php echo htmlspecialchars($this->table_name); ?></span>
|
||||
</div>
|
||||
<div class="dbm-title">
|
||||
<h1><?php echo htmlspecialchars($this->table_name); ?></h1>
|
||||
<span class="badge"><?php echo number_format($this->total_rows); ?> rows</span>
|
||||
</div>
|
||||
<div class="dbm-actions">
|
||||
<button type="button" id="btn-add-row" class="dbm-btn dbm-btn-success">
|
||||
<i data-lucide="plus"></i>
|
||||
Add Row
|
||||
</button>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/structure/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>" class="dbm-btn dbm-btn-secondary">
|
||||
<i data-lucide="settings"></i>
|
||||
Structure
|
||||
</a>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/export/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>" class="dbm-btn dbm-btn-secondary" target="_blank">
|
||||
<i data-lucide="download"></i>
|
||||
Export
|
||||
</a>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/delete/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>"
|
||||
class="dbm-btn dbm-btn-danger"
|
||||
data-confirm="Drop table '<?php echo htmlspecialchars($this->table_name); ?>'? This cannot be undone!">
|
||||
<i data-lucide="trash-2"></i>
|
||||
Drop Table
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dbm-content-body">
|
||||
<?php if (!empty($this->table_info)): ?>
|
||||
<div class="dbm-stats">
|
||||
<div class="dbm-stat">
|
||||
<div class="dbm-stat-value"><?php echo number_format($this->total_rows); ?></div>
|
||||
<div class="dbm-stat-label">Total Rows</div>
|
||||
</div>
|
||||
<div class="dbm-stat">
|
||||
<div class="dbm-stat-value"><?php echo count($this->columns); ?></div>
|
||||
<div class="dbm-stat-label">Columns</div>
|
||||
</div>
|
||||
<div class="dbm-stat">
|
||||
<div class="dbm-stat-value"><?php echo $this->table_info['total_size'] ?? '-'; ?></div>
|
||||
<div class="dbm-stat-label">Size</div>
|
||||
</div>
|
||||
<div class="dbm-stat">
|
||||
<div class="dbm-stat-value"><?php echo $this->table_info['engine'] ?? '-'; ?></div>
|
||||
<div class="dbm-stat-label">Engine</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="dbm-table-wrapper" id="data-table-wrapper"
|
||||
data-database="<?php echo htmlspecialchars($this->database_name); ?>"
|
||||
data-table="<?php echo htmlspecialchars($this->table_name); ?>"
|
||||
data-pk-column="<?php echo htmlspecialchars($pk_column ?? ''); ?>"
|
||||
style="max-height: 500px; overflow: auto;">
|
||||
<table class="dbm-table" id="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach ($this->columns as $col): ?>
|
||||
<th data-column="<?php echo htmlspecialchars($col['Field']); ?>" data-type="<?php echo htmlspecialchars($col['Type']); ?>">
|
||||
<?php if ($col['Key'] === 'PRI'): ?>
|
||||
<span style="color: var(--accent-green);" title="Primary Key">
|
||||
<i data-lucide="key-round" style="width: 12px; height: 12px; vertical-align: middle;"></i>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php echo htmlspecialchars($col['Field']); ?>
|
||||
</th>
|
||||
<?php endforeach; ?>
|
||||
<th style="width: 120px; text-align: center;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($this->rows)): ?>
|
||||
<tr class="empty-row">
|
||||
<td colspan="<?php echo count($this->columns) + 1; ?>" style="text-align: center; padding: 40px; color: var(--text-muted);">
|
||||
No data in this table. Click "Add Row" to insert data.
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($this->rows as $row): ?>
|
||||
<tr class="data-row" data-pk="<?php echo htmlspecialchars($pk_column ? ($row[$pk_column] ?? '') : ''); ?>">
|
||||
<?php foreach ($this->columns as $col): ?>
|
||||
<td class="editable-cell" data-column="<?php echo htmlspecialchars($col['Field']); ?>" data-original="<?php echo htmlspecialchars($row[$col['Field']] ?? ''); ?>">
|
||||
<span class="cell-display"><?php
|
||||
$value = $row[$col['Field']] ?? null;
|
||||
if ($value === null) {
|
||||
echo '<span class="null-value">NULL</span>';
|
||||
} else {
|
||||
$display = htmlspecialchars(substr($value, 0, 100));
|
||||
if (strlen($value) > 100) $display .= '...';
|
||||
echo $display;
|
||||
}
|
||||
?></span>
|
||||
<input type="text" class="cell-input dbm-form-input" style="display: none; width: 100%; padding: 4px 8px; font-size: 13px;" value="<?php echo htmlspecialchars($row[$col['Field']] ?? ''); ?>">
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<td class="actions-cell" style="text-align: center; white-space: nowrap;">
|
||||
<div class="view-actions">
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-secondary btn-edit-row" title="Edit">
|
||||
<i data-lucide="pencil" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-danger btn-delete-row" title="Delete">
|
||||
<i data-lucide="trash-2" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="edit-actions" style="display: none;">
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-success btn-save-row" title="Save">
|
||||
<i data-lucide="check" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-secondary btn-cancel-edit" title="Cancel">
|
||||
<i data-lucide="x" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php if ($total_pages > 1): ?>
|
||||
<div class="dbm-pagination">
|
||||
<div class="dbm-pagination-info">
|
||||
Showing <?php echo (($this->current_page - 1) * $this->per_page) + 1; ?> - <?php echo min($this->current_page * $this->per_page, $this->total_rows); ?> of <?php echo number_format($this->total_rows); ?>
|
||||
</div>
|
||||
<div class="dbm-pagination-controls">
|
||||
<?php if ($this->current_page > 1): ?>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/1" class="dbm-pagination-btn">First</a>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/<?php echo $this->current_page - 1; ?>" class="dbm-pagination-btn">Prev</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$start = max(1, $this->current_page - 2);
|
||||
$end = min($total_pages, $this->current_page + 2);
|
||||
for ($i = $start; $i <= $end; $i++):
|
||||
?>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/<?php echo $i; ?>"
|
||||
class="dbm-pagination-btn <?php echo $i === $this->current_page ? 'active' : ''; ?>"><?php echo $i; ?></a>
|
||||
<?php endfor; ?>
|
||||
|
||||
<?php if ($this->current_page < $total_pages): ?>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/<?php echo $this->current_page + 1; ?>" class="dbm-pagination-btn">Next</a>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/<?php echo $total_pages; ?>" class="dbm-pagination-btn">Last</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const wrapper = document.getElementById('data-table-wrapper');
|
||||
const table = document.getElementById('data-table');
|
||||
const database = wrapper.dataset.database;
|
||||
const tableName = wrapper.dataset.table;
|
||||
const pkColumn = wrapper.dataset.pkColumn;
|
||||
const baseUrl = '<?php echo Config::get('URL'); ?>';
|
||||
|
||||
// Get column info from table headers
|
||||
function getColumns() {
|
||||
const headers = table.querySelectorAll('thead th[data-column]');
|
||||
return Array.from(headers).map(th => ({
|
||||
name: th.dataset.column,
|
||||
type: th.dataset.type
|
||||
}));
|
||||
}
|
||||
|
||||
// Edit row
|
||||
table.addEventListener('click', function(e) {
|
||||
const editBtn = e.target.closest('.btn-edit-row');
|
||||
if (editBtn) {
|
||||
const row = editBtn.closest('tr');
|
||||
enterEditMode(row);
|
||||
}
|
||||
});
|
||||
|
||||
// Save row
|
||||
table.addEventListener('click', function(e) {
|
||||
const saveBtn = e.target.closest('.btn-save-row');
|
||||
if (saveBtn) {
|
||||
const row = saveBtn.closest('tr');
|
||||
saveRow(row);
|
||||
}
|
||||
});
|
||||
|
||||
// Cancel edit
|
||||
table.addEventListener('click', function(e) {
|
||||
const cancelBtn = e.target.closest('.btn-cancel-edit');
|
||||
if (cancelBtn) {
|
||||
const row = cancelBtn.closest('tr');
|
||||
cancelEdit(row);
|
||||
}
|
||||
});
|
||||
|
||||
// Delete row
|
||||
table.addEventListener('click', function(e) {
|
||||
const deleteBtn = e.target.closest('.btn-delete-row');
|
||||
if (deleteBtn) {
|
||||
const row = deleteBtn.closest('tr');
|
||||
if (confirm('Delete this row? This cannot be undone.')) {
|
||||
deleteRow(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add new row
|
||||
document.getElementById('btn-add-row').addEventListener('click', function() {
|
||||
addNewRow();
|
||||
});
|
||||
|
||||
function enterEditMode(row) {
|
||||
row.classList.add('editing');
|
||||
row.querySelectorAll('.cell-display').forEach(el => el.style.display = 'none');
|
||||
row.querySelectorAll('.cell-input').forEach(el => el.style.display = 'block');
|
||||
row.querySelector('.view-actions').style.display = 'none';
|
||||
row.querySelector('.edit-actions').style.display = 'inline-flex';
|
||||
}
|
||||
|
||||
function exitEditMode(row) {
|
||||
row.classList.remove('editing');
|
||||
row.querySelectorAll('.cell-display').forEach(el => el.style.display = 'inline');
|
||||
row.querySelectorAll('.cell-input').forEach(el => el.style.display = 'none');
|
||||
row.querySelector('.view-actions').style.display = 'inline-flex';
|
||||
row.querySelector('.edit-actions').style.display = 'none';
|
||||
}
|
||||
|
||||
function cancelEdit(row) {
|
||||
if (row.classList.contains('new-row')) {
|
||||
row.remove();
|
||||
// Show empty message if no rows left
|
||||
const remainingRows = table.querySelectorAll('tbody tr.data-row');
|
||||
if (remainingRows.length === 0) {
|
||||
const cols = getColumns();
|
||||
const emptyRow = document.createElement('tr');
|
||||
emptyRow.className = 'empty-row';
|
||||
emptyRow.innerHTML = '<td colspan="' + (cols.length + 1) + '" style="text-align: center; padding: 40px; color: var(--text-muted);">No data in this table. Click "Add Row" to insert data.</td>';
|
||||
table.querySelector('tbody').appendChild(emptyRow);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Restore original values
|
||||
row.querySelectorAll('.editable-cell').forEach(cell => {
|
||||
const original = cell.dataset.original;
|
||||
cell.querySelector('.cell-input').value = original;
|
||||
});
|
||||
exitEditMode(row);
|
||||
}
|
||||
|
||||
function saveRow(row) {
|
||||
const isNew = row.classList.contains('new-row');
|
||||
const pkValue = row.dataset.pk;
|
||||
const data = {};
|
||||
|
||||
row.querySelectorAll('.editable-cell').forEach(cell => {
|
||||
const column = cell.dataset.column;
|
||||
const input = cell.querySelector('.cell-input');
|
||||
data[column] = input.value;
|
||||
});
|
||||
|
||||
const url = isNew
|
||||
? baseUrl + 'table/insertRow/' + encodeURIComponent(database) + '/' + encodeURIComponent(tableName)
|
||||
: baseUrl + 'table/updateRow/' + encodeURIComponent(database) + '/' + encodeURIComponent(tableName);
|
||||
|
||||
const formData = new FormData();
|
||||
if (!isNew) {
|
||||
formData.append('pk_value', pkValue);
|
||||
}
|
||||
for (const key in data) {
|
||||
formData.append('data[' + key + ']', data[key]);
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
// Update display values
|
||||
row.querySelectorAll('.editable-cell').forEach(cell => {
|
||||
const input = cell.querySelector('.cell-input');
|
||||
const display = cell.querySelector('.cell-display');
|
||||
const value = input.value;
|
||||
cell.dataset.original = value;
|
||||
if (value === '' || value === null) {
|
||||
display.innerHTML = '<span class="null-value">NULL</span>';
|
||||
} else {
|
||||
display.textContent = value.length > 100 ? value.substring(0, 100) + '...' : value;
|
||||
}
|
||||
});
|
||||
|
||||
if (isNew && result.insert_id && pkColumn) {
|
||||
row.dataset.pk = result.insert_id;
|
||||
// Update the PK cell display
|
||||
const pkCell = row.querySelector('.editable-cell[data-column="' + pkColumn + '"]');
|
||||
if (pkCell) {
|
||||
pkCell.querySelector('.cell-input').value = result.insert_id;
|
||||
pkCell.querySelector('.cell-display').textContent = result.insert_id;
|
||||
pkCell.dataset.original = result.insert_id;
|
||||
}
|
||||
}
|
||||
|
||||
row.classList.remove('new-row');
|
||||
exitEditMode(row);
|
||||
} else {
|
||||
alert('Error: ' + result.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error saving row: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function deleteRow(row) {
|
||||
const pkValue = row.dataset.pk;
|
||||
|
||||
if (!pkValue) {
|
||||
alert('Cannot delete: no primary key');
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('pk_value', pkValue);
|
||||
|
||||
fetch(baseUrl + 'table/deleteRow/' + encodeURIComponent(database) + '/' + encodeURIComponent(tableName), {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
row.remove();
|
||||
// Show empty message if no rows left
|
||||
const remainingRows = table.querySelectorAll('tbody tr.data-row');
|
||||
if (remainingRows.length === 0) {
|
||||
const cols = getColumns();
|
||||
const emptyRow = document.createElement('tr');
|
||||
emptyRow.className = 'empty-row';
|
||||
emptyRow.innerHTML = '<td colspan="' + (cols.length + 1) + '" style="text-align: center; padding: 40px; color: var(--text-muted);">No data in this table. Click "Add Row" to insert data.</td>';
|
||||
table.querySelector('tbody').appendChild(emptyRow);
|
||||
}
|
||||
} else {
|
||||
alert('Error: ' + result.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error deleting row: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function addNewRow() {
|
||||
// Remove empty message if present
|
||||
const emptyRow = table.querySelector('tbody tr.empty-row');
|
||||
if (emptyRow) {
|
||||
emptyRow.remove();
|
||||
}
|
||||
|
||||
const columns = getColumns();
|
||||
const tr = document.createElement('tr');
|
||||
tr.className = 'data-row new-row editing';
|
||||
tr.dataset.pk = '';
|
||||
|
||||
columns.forEach(col => {
|
||||
const td = document.createElement('td');
|
||||
td.className = 'editable-cell';
|
||||
td.dataset.column = col.name;
|
||||
td.dataset.original = '';
|
||||
td.innerHTML = `
|
||||
<span class="cell-display" style="display: none;"><span class="null-value">NULL</span></span>
|
||||
<input type="text" class="cell-input dbm-form-input" style="display: block; width: 100%; padding: 4px 8px; font-size: 13px;" value="">
|
||||
`;
|
||||
tr.appendChild(td);
|
||||
});
|
||||
|
||||
// Actions cell
|
||||
const actionsTd = document.createElement('td');
|
||||
actionsTd.className = 'actions-cell';
|
||||
actionsTd.style.textAlign = 'center';
|
||||
actionsTd.style.whiteSpace = 'nowrap';
|
||||
actionsTd.innerHTML = `
|
||||
<div class="view-actions" style="display: none;">
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-secondary btn-edit-row" title="Edit">
|
||||
<i data-lucide="pencil" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-danger btn-delete-row" title="Delete">
|
||||
<i data-lucide="trash-2" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="edit-actions" style="display: inline-flex;">
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-success btn-save-row" title="Save">
|
||||
<i data-lucide="check" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
<button type="button" class="dbm-btn dbm-btn-sm dbm-btn-secondary btn-cancel-edit" title="Cancel">
|
||||
<i data-lucide="x" style="width: 12px; height: 12px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
lucide.createIcons();
|
||||
tr.appendChild(actionsTd);
|
||||
|
||||
// Insert at the top of tbody
|
||||
const tbody = table.querySelector('tbody');
|
||||
tbody.insertBefore(tr, tbody.firstChild);
|
||||
|
||||
// Focus first input
|
||||
const firstInput = tr.querySelector('.cell-input');
|
||||
if (firstInput) {
|
||||
firstInput.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
112
application/view/table/structure.php
Normal file
112
application/view/table/structure.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<div class="dbm-content-header">
|
||||
<div class="dbm-breadcrumb">
|
||||
<a href="<?php echo Config::get('URL'); ?>database/index">Databases</a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>database/show/<?php echo urlencode($this->database_name); ?>"><?php echo htmlspecialchars($this->database_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>"><?php echo htmlspecialchars($this->table_name); ?></a>
|
||||
<span class="separator">/</span>
|
||||
<span>Structure</span>
|
||||
</div>
|
||||
<div class="dbm-title">
|
||||
<h1>Structure: <?php echo htmlspecialchars($this->table_name); ?></h1>
|
||||
<span class="badge"><?php echo count($this->columns); ?> columns</span>
|
||||
</div>
|
||||
<div class="dbm-actions">
|
||||
<a href="<?php echo Config::get('URL'); ?>table/show/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>" class="dbm-btn dbm-btn-primary">
|
||||
<i data-lucide="list"></i>
|
||||
Browse Data
|
||||
</a>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/addColumn/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>" class="dbm-btn dbm-btn-success">
|
||||
<i data-lucide="plus"></i>
|
||||
Add Column
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dbm-content-body">
|
||||
<div class="dbm-card" style="margin-bottom: 24px;">
|
||||
<div class="dbm-card-header">
|
||||
<h3>Columns</h3>
|
||||
</div>
|
||||
<div class="dbm-table-wrapper" style="border: none; border-radius: 0;">
|
||||
<table class="dbm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Null</th>
|
||||
<th>Key</th>
|
||||
<th>Default</th>
|
||||
<th>Extra</th>
|
||||
<th style="width: 80px;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->columns as $col): ?>
|
||||
<tr>
|
||||
<td style="font-weight: 500;">
|
||||
<?php if ($col['Key'] === 'PRI'): ?>
|
||||
<span class="key-column">
|
||||
<i data-lucide="key-round" style="width: 12px; height: 12px; vertical-align: middle; margin-right: 4px;"></i>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php echo htmlspecialchars($col['Field']); ?>
|
||||
</td>
|
||||
<td><span class="type-column"><?php echo htmlspecialchars($col['Type']); ?></span></td>
|
||||
<td><?php echo $col['Null'] === 'YES' ? '<span style="color: var(--accent-orange);">YES</span>' : 'NO'; ?></td>
|
||||
<td>
|
||||
<?php if ($col['Key'] === 'PRI'): ?>
|
||||
<span style="color: var(--accent-green);">PRIMARY</span>
|
||||
<?php elseif ($col['Key'] === 'UNI'): ?>
|
||||
<span style="color: var(--accent-blue);">UNIQUE</span>
|
||||
<?php elseif ($col['Key'] === 'MUL'): ?>
|
||||
<span style="color: var(--accent-purple);">INDEX</span>
|
||||
<?php else: ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?php echo $col['Default'] !== null ? htmlspecialchars($col['Default']) : '<span class="null-value">NULL</span>'; ?></td>
|
||||
<td><span class="type-column"><?php echo htmlspecialchars($col['Extra']); ?></span></td>
|
||||
<td>
|
||||
<a href="<?php echo Config::get('URL'); ?>table/dropColumn/<?php echo urlencode($this->database_name); ?>/<?php echo urlencode($this->table_name); ?>/<?php echo urlencode($col['Field']); ?>"
|
||||
class="dbm-btn dbm-btn-sm dbm-btn-danger"
|
||||
data-confirm="Drop column '<?php echo htmlspecialchars($col['Field']); ?>'? This cannot be undone!">Drop</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($this->indexes)): ?>
|
||||
<div class="dbm-card">
|
||||
<div class="dbm-card-header">
|
||||
<h3>Indexes</h3>
|
||||
</div>
|
||||
<div class="dbm-table-wrapper" style="border: none; border-radius: 0;">
|
||||
<table class="dbm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key Name</th>
|
||||
<th>Column</th>
|
||||
<th>Unique</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->indexes as $idx): ?>
|
||||
<tr>
|
||||
<td style="font-weight: 500;"><?php echo htmlspecialchars($idx['Key_name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($idx['Column_name']); ?></td>
|
||||
<td><?php echo $idx['Non_unique'] ? '<span style="color: var(--text-muted);">No</span>' : '<span style="color: var(--accent-green);">Yes</span>'; ?></td>
|
||||
<td><span class="type-column"><?php echo htmlspecialchars($idx['Index_type']); ?></span></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
Reference in New Issue
Block a user