mirror of
https://github.com/olehomelchenko/astrolabe-nvc.git
synced 2025-12-21 21:22:23 +00:00
feat: Implement Alpine.js for dynamic rendering and state management of the dataset details panel.
This commit is contained in:
60
index.html
60
index.html
@@ -289,7 +289,7 @@
|
||||
No datasets yet. Click "New Dataset" to create one.
|
||||
</div>
|
||||
</div>
|
||||
<div class="dataset-details" id="dataset-details" style="display: none;">
|
||||
<div class="dataset-details" x-data="datasetDetails()" x-show="isVisible" id="dataset-details">
|
||||
<div class="dataset-detail-section">
|
||||
<div class="dataset-actions">
|
||||
<button class="btn btn-modal primary" id="edit-dataset-btn"
|
||||
@@ -308,15 +308,15 @@
|
||||
|
||||
<div class="dataset-detail-header">Name</div>
|
||||
<input type="text" id="dataset-detail-name" class="input"
|
||||
placeholder="Dataset name..." />
|
||||
placeholder="Dataset name..." :value="dataset?.name" @input="handleNameChange" />
|
||||
|
||||
<div class="dataset-detail-header">Comment</div>
|
||||
<textarea id="dataset-detail-comment" class="input textarea"
|
||||
placeholder="Add a comment..." rows="3"></textarea>
|
||||
placeholder="Add a comment..." rows="3" :value="dataset?.comment" @input="handleCommentChange"></textarea>
|
||||
|
||||
<div class="dataset-detail-header-row">
|
||||
<span class="dataset-detail-header">Overview</span>
|
||||
<button class="btn btn-icon large" id="refresh-metadata-btn" style="display: none;"
|
||||
<button class="btn btn-icon large" id="refresh-metadata-btn" x-show="isURLDataset"
|
||||
title="Refresh metadata from URL">🔄</button>
|
||||
</div>
|
||||
<div class="dataset-overview-grid">
|
||||
@@ -325,23 +325,29 @@
|
||||
<div class="stats-box">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Rows:</span>
|
||||
<span id="dataset-detail-rows">0</span>
|
||||
<span x-text="formatRowCount(dataset?.rowCount)">0</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Columns:</span>
|
||||
<span id="dataset-detail-columns">0</span>
|
||||
<span x-text="formatColumnCount(dataset?.columnCount)">0</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Size:</span>
|
||||
<span id="dataset-detail-size">0 B</span>
|
||||
<span x-text="formatBytes(dataset?.size)">0 B</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-section" id="columns-section" style="display: none;">
|
||||
<div class="overview-section" x-show="showColumnsSection">
|
||||
<div class="overview-section-title">Columns</div>
|
||||
<div class="columns-list" id="dataset-detail-columns-list">
|
||||
<!-- Dynamically populated with column names and types -->
|
||||
<div class="columns-list">
|
||||
<template x-for="col in dataset?.columnTypes" :key="col.name">
|
||||
<div class="column-item">
|
||||
<span class="column-type-icon" x-html="getTypeIcon(col.type)"></span>
|
||||
<span class="column-name" x-text="col.name"></span>
|
||||
<span class="column-type" x-text="col.type"></span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -350,11 +356,11 @@
|
||||
<div class="stats-box">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Created:</span>
|
||||
<span id="dataset-detail-created">-</span>
|
||||
<span x-text="formatDate(dataset?.created)">-</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Modified:</span>
|
||||
<span id="dataset-detail-modified">-</span>
|
||||
<span id="dataset-detail-modified" x-text="formatDate(dataset?.modified)">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -362,21 +368,35 @@
|
||||
|
||||
<div class="dataset-detail-header-row">
|
||||
<span class="dataset-detail-header">Preview</span>
|
||||
<div class="preview-toggle-group" id="preview-toggle-group" style="display: none;">
|
||||
<button class="btn btn-toggle small active" id="preview-raw-btn"
|
||||
<div class="preview-toggle-group" x-show="showPreviewToggle">
|
||||
<button class="btn btn-toggle small"
|
||||
:class="{ 'active': $store.datasets.previewMode === 'raw' }"
|
||||
@click="setPreviewMode('raw')"
|
||||
title="Show raw data preview">Raw</button>
|
||||
<button class="btn btn-toggle small" id="preview-table-btn"
|
||||
<button class="btn btn-toggle small"
|
||||
:class="{ 'active': $store.datasets.previewMode === 'table' }"
|
||||
@click="setPreviewMode('table')"
|
||||
title="Show data in table format with type detection">Table</button>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="dataset-preview" class="preview-box large"></pre>
|
||||
<div id="dataset-preview-table" class="preview-table-container" style="display: none;">
|
||||
<pre id="dataset-preview" class="preview-box large"
|
||||
x-show="$store.datasets.previewMode === 'raw'"></pre>
|
||||
<div id="dataset-preview-table" class="preview-table-container"
|
||||
x-show="$store.datasets.previewMode === 'table'">
|
||||
</div>
|
||||
|
||||
<div id="dataset-snippets-section" style="display: none;">
|
||||
<div x-show="linkedSnippets.length > 0">
|
||||
<div class="dataset-detail-header">Linked Snippets</div>
|
||||
<div class="stats-box" id="dataset-snippets">
|
||||
<!-- Dynamically populated by updateLinkedSnippets() -->
|
||||
<div class="stats-box">
|
||||
<template x-for="snippet in linkedSnippets" :key="snippet.id">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">📄</span>
|
||||
<span>
|
||||
<a href="#" @click.prevent="openLinkedSnippet(snippet.id)"
|
||||
class="snippet-link" x-text="snippet.name"></a>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.store('datasets', {
|
||||
currentDatasetId: null,
|
||||
currentDatasetData: null
|
||||
currentDatasetData: null,
|
||||
previewMode: 'raw', // 'raw' or 'table'
|
||||
formMode: null, // null, 'create', or 'edit'
|
||||
editingDatasetId: null,
|
||||
originalSchema: null
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +19,11 @@ function datasetList() {
|
||||
|
||||
async init() {
|
||||
await this.loadDatasets();
|
||||
|
||||
// Listen for refresh events (fallback for when Alpine.$data doesn't work)
|
||||
this.$el.addEventListener('dataset-list-refresh', async () => {
|
||||
await this.loadDatasets();
|
||||
});
|
||||
},
|
||||
|
||||
async loadDatasets() {
|
||||
@@ -46,6 +55,93 @@ function datasetList() {
|
||||
};
|
||||
}
|
||||
|
||||
// Alpine.js component for dataset details panel
|
||||
function datasetDetails() {
|
||||
return {
|
||||
get dataset() {
|
||||
return this.$store.datasets.currentDatasetData;
|
||||
},
|
||||
|
||||
get isVisible() {
|
||||
return this.$store.datasets.currentDatasetId !== null && this.dataset !== null;
|
||||
},
|
||||
|
||||
get isURLDataset() {
|
||||
return this.dataset && this.dataset.source === 'url';
|
||||
},
|
||||
|
||||
get showColumnsSection() {
|
||||
return this.dataset && this.dataset.columnTypes && this.dataset.columnTypes.length > 0;
|
||||
},
|
||||
|
||||
get canShowTable() {
|
||||
if (!this.dataset) return false;
|
||||
return ['json', 'csv', 'tsv'].includes(this.dataset.format);
|
||||
},
|
||||
|
||||
get showPreviewToggle() {
|
||||
if (!this.dataset) return false;
|
||||
if (this.isURLDataset) {
|
||||
return window.urlPreviewCache && window.urlPreviewCache[this.dataset.id] && this.canShowTable;
|
||||
}
|
||||
return this.canShowTable;
|
||||
},
|
||||
|
||||
get hasURLPreview() {
|
||||
return this.dataset && window.urlPreviewCache && window.urlPreviewCache[this.dataset.id];
|
||||
},
|
||||
|
||||
get linkedSnippets() {
|
||||
if (!this.dataset) return [];
|
||||
const snippets = SnippetStorage.loadSnippets();
|
||||
return snippets.filter(snippet =>
|
||||
snippet.datasetRefs && snippet.datasetRefs.includes(this.dataset.name)
|
||||
);
|
||||
},
|
||||
|
||||
formatBytes(bytes) {
|
||||
return formatBytes(bytes);
|
||||
},
|
||||
|
||||
formatDate(timestamp) {
|
||||
return new Date(timestamp).toLocaleString();
|
||||
},
|
||||
|
||||
formatRowCount(count) {
|
||||
return count !== null ? count : 'N/A';
|
||||
},
|
||||
|
||||
formatColumnCount(count) {
|
||||
return count !== null ? count : 'N/A';
|
||||
},
|
||||
|
||||
getTypeIcon(type) {
|
||||
return getTypeIcon(type);
|
||||
},
|
||||
|
||||
handleNameChange() {
|
||||
debouncedAutoSaveDatasetMeta();
|
||||
},
|
||||
|
||||
handleCommentChange() {
|
||||
debouncedAutoSaveDatasetMeta();
|
||||
},
|
||||
|
||||
setPreviewMode(mode) {
|
||||
this.$store.datasets.previewMode = mode;
|
||||
if (mode === 'raw') {
|
||||
showRawPreview(this.dataset);
|
||||
} else {
|
||||
showTablePreview(this.dataset);
|
||||
}
|
||||
},
|
||||
|
||||
openLinkedSnippet(snippetId) {
|
||||
openSnippetFromDataset(snippetId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const DB_NAME = 'astrolabe-datasets';
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = 'datasets';
|
||||
@@ -396,11 +492,34 @@ async function fetchURLMetadata(url, format) {
|
||||
// Render dataset list in modal
|
||||
// Alpine.js now handles rendering, this just triggers a refresh
|
||||
async function renderDatasetList() {
|
||||
// Wait a tick for Alpine to initialize if needed
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
const listView = document.getElementById('dataset-list-view');
|
||||
if (listView && listView.__x) {
|
||||
const component = Alpine.$data(listView);
|
||||
let component = null;
|
||||
|
||||
// Try multiple methods to get the Alpine component
|
||||
if (listView && typeof Alpine !== 'undefined') {
|
||||
// Method 1: Try Alpine.$data (standard approach)
|
||||
try {
|
||||
component = Alpine.$data(listView);
|
||||
} catch (e) {
|
||||
// Method 2: Try accessing _x_dataStack (Alpine 3.x internal API)
|
||||
if (listView._x_dataStack && listView._x_dataStack.length > 0) {
|
||||
component = listView._x_dataStack[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (component && component.loadDatasets) {
|
||||
await component.loadDatasets();
|
||||
} else {
|
||||
// Fallback: Trigger refresh via custom event
|
||||
if (typeof Alpine !== 'undefined' && listView) {
|
||||
Alpine.nextTick(() => {
|
||||
const evt = new CustomEvent('dataset-list-refresh');
|
||||
listView.dispatchEvent(evt);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,93 +529,24 @@ async function selectDataset(datasetId, updateURL = true) {
|
||||
const dataset = await DatasetStorage.getDataset(datasetId);
|
||||
if (!dataset) return;
|
||||
|
||||
// Update Alpine store selection (Alpine handles highlighting via :class binding)
|
||||
if (typeof Alpine !== 'undefined' && Alpine.store('datasets')) {
|
||||
// Update Alpine store - this triggers all reactive UI updates
|
||||
Alpine.store('datasets').currentDatasetId = datasetId;
|
||||
}
|
||||
|
||||
// Show details panel
|
||||
const detailsPanel = document.getElementById('dataset-details');
|
||||
detailsPanel.style.display = 'block';
|
||||
|
||||
// Show/hide refresh button for URL datasets
|
||||
const refreshBtn = document.getElementById('refresh-metadata-btn');
|
||||
if (dataset.source === 'url') {
|
||||
refreshBtn.style.display = 'flex';
|
||||
} else {
|
||||
refreshBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Populate details
|
||||
document.getElementById('dataset-detail-name').value = dataset.name;
|
||||
document.getElementById('dataset-detail-comment').value = dataset.comment;
|
||||
document.getElementById('dataset-detail-rows').textContent = dataset.rowCount !== null ? dataset.rowCount : 'N/A';
|
||||
document.getElementById('dataset-detail-columns').textContent = dataset.columnCount !== null ? dataset.columnCount : 'N/A';
|
||||
document.getElementById('dataset-detail-size').textContent = formatBytes(dataset.size);
|
||||
document.getElementById('dataset-detail-created').textContent = new Date(dataset.created).toLocaleString();
|
||||
document.getElementById('dataset-detail-modified').textContent = new Date(dataset.modified).toLocaleString();
|
||||
|
||||
// Populate columns list with types
|
||||
const columnsSection = document.getElementById('columns-section');
|
||||
const columnsList = document.getElementById('dataset-detail-columns-list');
|
||||
|
||||
if (dataset.columnTypes && dataset.columnTypes.length > 0) {
|
||||
columnsSection.style.display = 'block';
|
||||
|
||||
const columnsHTML = dataset.columnTypes.map(col => {
|
||||
const icon = getTypeIcon(col.type);
|
||||
return `
|
||||
<div class="column-item">
|
||||
<span class="column-type-icon">${icon}</span>
|
||||
<span class="column-name">${col.name}</span>
|
||||
<span class="column-type">${col.type}</span>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
columnsList.innerHTML = columnsHTML;
|
||||
} else {
|
||||
columnsSection.style.display = 'none';
|
||||
}
|
||||
|
||||
// Show/hide preview toggle based on data type
|
||||
const toggleGroup = document.getElementById('preview-toggle-group');
|
||||
const canShowTable = (dataset.format === 'json' || dataset.format === 'csv' || dataset.format === 'tsv');
|
||||
Alpine.store('datasets').currentDatasetData = dataset;
|
||||
Alpine.store('datasets').previewMode = 'raw';
|
||||
|
||||
// Handle preview display
|
||||
if (dataset.source === 'url') {
|
||||
// For URL datasets, check if we have cached preview data
|
||||
if (window.urlPreviewCache && window.urlPreviewCache[dataset.id]) {
|
||||
if (canShowTable) {
|
||||
toggleGroup.style.display = 'flex';
|
||||
} else {
|
||||
toggleGroup.style.display = 'none';
|
||||
}
|
||||
showRawPreview(dataset);
|
||||
} else {
|
||||
// Show load preview option
|
||||
toggleGroup.style.display = 'none';
|
||||
showURLPreviewPrompt(dataset);
|
||||
}
|
||||
} else {
|
||||
// For inline datasets
|
||||
if (canShowTable) {
|
||||
toggleGroup.style.display = 'flex';
|
||||
} else {
|
||||
toggleGroup.style.display = 'none';
|
||||
}
|
||||
// For inline datasets, show preview immediately
|
||||
showRawPreview(dataset);
|
||||
}
|
||||
|
||||
// Store current dataset ID and data in Alpine store
|
||||
Alpine.store('datasets').currentDatasetId = datasetId;
|
||||
Alpine.store('datasets').currentDatasetData = dataset;
|
||||
|
||||
// Update linked snippets display
|
||||
updateLinkedSnippets(dataset);
|
||||
|
||||
// Initialize auto-save for detail fields
|
||||
initializeDatasetDetailAutoSave();
|
||||
|
||||
// Update URL state (URLState.update will add 'dataset-' prefix)
|
||||
if (updateURL) {
|
||||
URLState.update({ view: 'datasets', snippetId: null, datasetId: datasetId });
|
||||
@@ -594,20 +644,7 @@ async function loadURLPreview(dataset) {
|
||||
|
||||
// Show raw preview
|
||||
function showRawPreview(dataset) {
|
||||
const rawBtn = document.getElementById('preview-raw-btn');
|
||||
const tableBtn = document.getElementById('preview-table-btn');
|
||||
const previewBox = document.getElementById('dataset-preview');
|
||||
const tableContainer = document.getElementById('dataset-preview-table');
|
||||
|
||||
// Update button states
|
||||
if (rawBtn && tableBtn) {
|
||||
rawBtn.classList.add('active');
|
||||
tableBtn.classList.remove('active');
|
||||
}
|
||||
|
||||
// Show raw, hide table
|
||||
previewBox.style.display = 'block';
|
||||
tableContainer.style.display = 'none';
|
||||
|
||||
// Generate preview text
|
||||
let previewText;
|
||||
@@ -687,19 +724,8 @@ function getTypeIcon(type) {
|
||||
|
||||
// Show table preview
|
||||
function showTablePreview(dataset) {
|
||||
const rawBtn = document.getElementById('preview-raw-btn');
|
||||
const tableBtn = document.getElementById('preview-table-btn');
|
||||
const previewBox = document.getElementById('dataset-preview');
|
||||
const tableContainer = document.getElementById('dataset-preview-table');
|
||||
|
||||
// Update button states
|
||||
rawBtn.classList.remove('active');
|
||||
tableBtn.classList.add('active');
|
||||
|
||||
// Hide raw, show table
|
||||
previewBox.style.display = 'none';
|
||||
tableContainer.style.display = 'block';
|
||||
|
||||
// Generate table HTML
|
||||
let tableHTML = '';
|
||||
const maxRows = 20; // Show first 20 rows
|
||||
@@ -810,30 +836,11 @@ function showTablePreview(dataset) {
|
||||
tableContainer.innerHTML = tableHTML;
|
||||
}
|
||||
|
||||
// Update linked snippets display in dataset details panel
|
||||
function updateLinkedSnippets(dataset) {
|
||||
// Find all snippets that reference this dataset
|
||||
const snippets = SnippetStorage.loadSnippets();
|
||||
const linkedSnippets = snippets.filter(snippet =>
|
||||
snippet.datasetRefs && snippet.datasetRefs.includes(dataset.name)
|
||||
);
|
||||
|
||||
updateGenericLinkedItems(
|
||||
linkedSnippets,
|
||||
'dataset-snippets',
|
||||
'dataset-snippets-section',
|
||||
(snippet) => `
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">📄</span>
|
||||
<span>
|
||||
<a href="#snippet-${snippet.id}" class="snippet-link" data-linked-item-id="${snippet.id}">${snippet.name}</a>
|
||||
</span>
|
||||
</div>
|
||||
`,
|
||||
(snippetId) => {
|
||||
openSnippetFromDataset(snippetId);
|
||||
}
|
||||
);
|
||||
// Update linked snippets display in dataset details panel (deprecated - now handled by Alpine)
|
||||
// This function is kept for backwards compatibility but is no longer used
|
||||
function updateLinkedSnippets() {
|
||||
// Linked snippets are now displayed reactively via Alpine component
|
||||
// See datasetDetails() component's linkedSnippets getter
|
||||
}
|
||||
|
||||
// Close dataset manager and open snippet
|
||||
@@ -1153,10 +1160,10 @@ function setupDatasetInputHandler() {
|
||||
|
||||
// Show new dataset form
|
||||
function showNewDatasetForm(updateURL = true) {
|
||||
// Set mode to create
|
||||
window.datasetFormMode = 'create';
|
||||
window.editingDatasetId = null;
|
||||
window.originalSchema = null;
|
||||
// Set mode to create in Alpine store
|
||||
Alpine.store('datasets').formMode = 'create';
|
||||
Alpine.store('datasets').editingDatasetId = null;
|
||||
Alpine.store('datasets').originalSchema = null;
|
||||
|
||||
document.getElementById('dataset-list-view').style.display = 'none';
|
||||
document.getElementById('dataset-form-view').style.display = 'block';
|
||||
@@ -1188,12 +1195,12 @@ async function showEditDatasetForm(datasetId, updateURL = true) {
|
||||
const dataset = await DatasetStorage.getDataset(datasetId);
|
||||
if (!dataset) return;
|
||||
|
||||
// Set mode to edit
|
||||
window.datasetFormMode = 'edit';
|
||||
window.editingDatasetId = datasetId;
|
||||
// Set mode to edit in Alpine store
|
||||
Alpine.store('datasets').formMode = 'edit';
|
||||
Alpine.store('datasets').editingDatasetId = datasetId;
|
||||
|
||||
// Store original schema for comparison
|
||||
window.originalSchema = dataset.columns ? [...dataset.columns] : [];
|
||||
Alpine.store('datasets').originalSchema = dataset.columns ? [...dataset.columns] : [];
|
||||
|
||||
document.getElementById('dataset-list-view').style.display = 'none';
|
||||
document.getElementById('dataset-form-view').style.display = 'block';
|
||||
@@ -1280,7 +1287,7 @@ function showSchemaWarning(oldSchema, newSchema) {
|
||||
// Check for schema changes
|
||||
function checkSchemaChanges() {
|
||||
// Only check in edit mode
|
||||
if (window.datasetFormMode !== 'edit' || !window.originalSchema) {
|
||||
if (Alpine.store('datasets').formMode !== 'edit' || !Alpine.store('datasets').originalSchema) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1312,7 +1319,7 @@ function checkSchemaChanges() {
|
||||
}
|
||||
|
||||
// Compare schemas
|
||||
const originalSchema = window.originalSchema || [];
|
||||
const originalSchema = Alpine.store('datasets').originalSchema || [];
|
||||
|
||||
if (newSchema.length === 0 && originalSchema.length === 0) {
|
||||
hideSchemaWarning();
|
||||
@@ -1336,9 +1343,9 @@ function checkSchemaChanges() {
|
||||
function hideNewDatasetForm(updateURL = true) {
|
||||
document.getElementById('dataset-list-view').style.display = 'block';
|
||||
document.getElementById('dataset-form-view').style.display = 'none';
|
||||
window.datasetFormMode = null;
|
||||
window.editingDatasetId = null;
|
||||
window.originalSchema = null;
|
||||
Alpine.store('datasets').formMode = null;
|
||||
Alpine.store('datasets').editingDatasetId = null;
|
||||
Alpine.store('datasets').originalSchema = null;
|
||||
hideSchemaWarning();
|
||||
|
||||
// Update URL to dataset list view
|
||||
@@ -1414,9 +1421,9 @@ async function saveNewDataset() {
|
||||
}
|
||||
|
||||
try {
|
||||
if (window.datasetFormMode === 'edit') {
|
||||
if (Alpine.store('datasets').formMode === 'edit') {
|
||||
// Edit mode - update existing dataset
|
||||
const datasetId = window.editingDatasetId;
|
||||
const datasetId = Alpine.store('datasets').editingDatasetId;
|
||||
|
||||
// Check if name already exists (excluding current dataset)
|
||||
if (await DatasetStorage.nameExists(name, datasetId)) {
|
||||
@@ -1729,7 +1736,7 @@ async function importDatasetFromFile(fileInput) {
|
||||
}
|
||||
|
||||
// Create dataset
|
||||
await DatasetStorage.createDataset(
|
||||
const dataset = await DatasetStorage.createDataset(
|
||||
datasetName,
|
||||
data,
|
||||
format,
|
||||
@@ -1740,6 +1747,9 @@ async function importDatasetFromFile(fileInput) {
|
||||
// Refresh the list
|
||||
await renderDatasetList();
|
||||
|
||||
// Select the newly created dataset
|
||||
await selectDataset(dataset.id);
|
||||
|
||||
// Show success message with rename notification if applicable
|
||||
if (wasRenamed) {
|
||||
Toast.warning(`Dataset name "${baseName}" was already taken, so your dataset was automatically renamed to "${datasetName}".`);
|
||||
@@ -1818,6 +1828,9 @@ async function autoSaveDatasetMeta() {
|
||||
comment: newComment
|
||||
});
|
||||
|
||||
// Update Alpine store with updated dataset
|
||||
Alpine.store('datasets').currentDatasetData = updatedDataset;
|
||||
|
||||
// If name changed, update all snippets that reference this dataset
|
||||
if (nameChanged && newName) {
|
||||
const snippets = SnippetStorage.loadSnippets();
|
||||
@@ -1843,23 +1856,11 @@ async function autoSaveDatasetMeta() {
|
||||
if (affectedSnippets.length > 0) {
|
||||
Toast.success(`Updated ${affectedSnippets.length} snippet${affectedSnippets.length > 1 ? 's' : ''}`);
|
||||
}
|
||||
|
||||
// Refresh linked snippets display
|
||||
updateLinkedSnippets(updatedDataset);
|
||||
}
|
||||
|
||||
// Update the modified timestamp in the UI
|
||||
document.getElementById('dataset-detail-modified').textContent = new Date(updatedDataset.modified).toLocaleString();
|
||||
|
||||
// Update the dataset list display to reflect the new name
|
||||
await renderDatasetList();
|
||||
|
||||
// Restore selection after re-render
|
||||
const selectedItem = document.querySelector(`[data-item-id="${dataset.id}"]`);
|
||||
if (selectedItem) {
|
||||
selectedItem.classList.add('selected');
|
||||
}
|
||||
|
||||
// Refresh visualization if a snippet is open
|
||||
if (Alpine.store('snippets').currentSnippetId && typeof renderVisualization === 'function') {
|
||||
await renderVisualization();
|
||||
@@ -1873,20 +1874,9 @@ function debouncedAutoSaveDatasetMeta() {
|
||||
datasetMetaAutoSaveTimeout = setTimeout(autoSaveDatasetMeta, 1000);
|
||||
}
|
||||
|
||||
// Initialize auto-save for dataset detail fields
|
||||
// Initialize auto-save for dataset detail fields (deprecated - now handled by Alpine)
|
||||
// This function is kept for backwards compatibility but is no longer used
|
||||
function initializeDatasetDetailAutoSave() {
|
||||
const nameField = document.getElementById('dataset-detail-name');
|
||||
const commentField = document.getElementById('dataset-detail-comment');
|
||||
|
||||
if (nameField) {
|
||||
// Remove any existing event listener to prevent duplicates
|
||||
nameField.removeEventListener('input', debouncedAutoSaveDatasetMeta);
|
||||
nameField.addEventListener('input', debouncedAutoSaveDatasetMeta);
|
||||
}
|
||||
|
||||
if (commentField) {
|
||||
// Remove any existing event listener to prevent duplicates
|
||||
commentField.removeEventListener('input', debouncedAutoSaveDatasetMeta);
|
||||
commentField.addEventListener('input', debouncedAutoSaveDatasetMeta);
|
||||
}
|
||||
// Auto-save is now handled directly by Alpine @input handlers
|
||||
// See datasetDetails() component's handleNameChange and handleCommentChange methods
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user