diff --git a/datasette/static/app.css b/datasette/static/app.css index b430e208..30c4855c 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -1865,6 +1865,7 @@ textarea.row-edit-input { margin: 0; } +.row-edit-bulk-note label, .row-edit-bulk-note .button-as-link { font: inherit; } @@ -1924,10 +1925,11 @@ textarea.row-edit-input { border-bottom: 1px solid var(--rule); border-right: 1px solid var(--rule); max-width: 18rem; + overflow-wrap: anywhere; padding: 6px 8px; text-align: left; vertical-align: top; - white-space: nowrap; + white-space: normal; } .row-edit-bulk-preview-table th { @@ -2296,6 +2298,11 @@ select.table-create-input { margin: 0; } +.table-create-data-note label, +.table-create-data-note .button-as-link { + font: inherit; +} + .table-create-data-preview { display: grid; gap: 10px; @@ -2335,10 +2342,11 @@ select.table-create-input { border-bottom: 1px solid var(--rule); border-right: 1px solid var(--rule); max-width: 18rem; + overflow-wrap: anywhere; padding: 6px 8px; text-align: left; vertical-align: top; - white-space: nowrap; + white-space: normal; } .table-create-data-preview-table th { diff --git a/datasette/static/edit-tools.js b/datasette/static/edit-tools.js index 0415d772..87b63838 100644 --- a/datasette/static/edit-tools.js +++ b/datasette/static/edit-tools.js @@ -1850,6 +1850,36 @@ function resetTableCreateDataPreview(state) { syncTableCreateModeUi(state); } +function tableCreateTableNameFromFileName(fileName) { + var baseName = (fileName || "").replace(/^.*[\\/]/, ""); + var nameWithoutExtension = baseName.replace(/\.[^.]*$/, ""); + return nameWithoutExtension + .trim() + .replace(/\s+/g, "_") + .toLowerCase() + .replace(/[^a-z0-9_]/g, ""); +} + +async function loadTableCreateDataTextFile(state, file) { + if (!file) { + return; + } + try { + var text = await readTextFile(file); + var tableName = tableCreateTableNameFromFileName(file.name); + if (tableName) { + state.tableName.value = tableName; + state.tableName.dispatchEvent(new Event("input", { bubbles: true })); + } + state.dataTextarea.value = text; + state.dataTextarea.dispatchEvent(new Event("input", { bubbles: true })); + clearTableCreateDialogError(state); + state.dataTextarea.focus(); + } catch (_error) { + showTableCreateDialogError(state, "Could not read that text file."); + } +} + function previewTableCreateDataRows(state) { clearTableCreateDialogError(state); resetTableCreateDataPreview(state); @@ -2152,9 +2182,9 @@ function ensureTableCreateDialog(manager) { @@ -2182,6 +2212,8 @@ function ensureTableCreateDialog(manager) { dataPanel: dialog.querySelector(".table-create-data"), dataEditor: dialog.querySelector(".table-create-data-editor"), dataTextarea: dialog.querySelector(".table-create-data-textarea"), + dataOpenFileButton: dialog.querySelector(".table-create-data-open-file"), + dataFileInput: dialog.querySelector(".table-create-data-file-input"), dataPreview: dialog.querySelector(".table-create-data-preview"), createFromDataLink: dialog.querySelector(".table-create-from-data"), manualCreateLink: dialog.querySelector(".table-create-manual"), @@ -2251,6 +2283,25 @@ function ensureTableCreateDialog(manager) { clearTableCreateDialogError(tableCreateDialogState); }); + tableCreateDialogState.dataOpenFileButton.addEventListener( + "click", + function () { + tableCreateDialogState.dataFileInput.click(); + }, + ); + + tableCreateDialogState.dataFileInput.addEventListener( + "change", + async function (ev) { + var files = ev.target.files; + await loadTableCreateDataTextFile( + tableCreateDialogState, + files && files.length ? files[0] : null, + ); + ev.target.value = ""; + }, + ); + tableCreateDialogState.dataTextarea.addEventListener( "dragenter", function (ev) { @@ -2291,20 +2342,7 @@ function ensureTableCreateDialog(manager) { if (!files || !files.length) { return; } - try { - tableCreateDialogState.dataTextarea.value = await readTextFile( - files[0], - ); - tableCreateDialogState.dataTextarea.dispatchEvent( - new Event("input", { bubbles: true }), - ); - clearTableCreateDialogError(tableCreateDialogState); - } catch (_error) { - showTableCreateDialogError( - tableCreateDialogState, - "Could not read that text file.", - ); - } + await loadTableCreateDataTextFile(tableCreateDialogState, files[0]); }, ); @@ -6378,9 +6416,9 @@ function ensureRowEditDialog(manager) {