Drop custom auth dialog; rely on browser Basic Auth handling

Remove ImportDialog and all manual credential management. The browser
handles 401 challenges natively for same-origin fetch requests — it
shows its own credential prompt, retries, and caches the result for
the session. No JS-level auth code is needed.

- api.js: remove authHeader() and all credentials parameters
- store.js: remove credentials field
- ImportDialog.js: deleted
- AppShell.js: remove showImport/openImport/onMounted dialog machinery;
  pass importOnLoad through to PaneCP
- PaneCP.js: inline doImport() (was in ImportDialog); auto-triggers on
  mount when importOnLoad is true; shows inline import error on failure
- StatusPoller.js: remove credentials arg from fetchStatus()
- style.css: remove .se-import-dialog and .se-overlay blocks
This commit is contained in:
c0dev0id
2026-06-30 09:32:44 +02:00
parent 86b14dfaa3
commit 67c75781d8
7 changed files with 45 additions and 164 deletions

View File

@@ -1,5 +1,6 @@
import { h, ref, watch } from 'vue';
import { fetchScoreText, putScoreText, fetchAudioWidget, URLS } from '../api.js';
import { h, ref, watch, onMounted } from 'vue';
import { fetchAstLog, fetchScoreText, putScoreText, fetchAudioWidget, URLS } from '../api.js';
import { parseAstLog, buildModel } from '../ast-parser.js';
import { patchScore } from '../exporter.js';
import { StatusPoller } from './StatusPoller.js';
@@ -44,8 +45,10 @@ function shortView(node) {
}
export const PaneCP = {
props: ['store', 'onImportClick', 'onFocusFO'],
props: ['store', 'importOnLoad', 'onFocusFO'],
setup(props) {
const importing = ref(false);
const importError = ref('');
const exporting = ref(false);
const exportError = ref('');
const audioWidgetHtml = ref('');
@@ -61,18 +64,33 @@ export const PaneCP = {
},
);
async function doImport() {
if (props.store.isDirty) return;
importError.value = '';
importing.value = true;
try {
const text = await fetchAstLog();
props.store.scoreModel = buildModel(parseAstLog(text));
props.store.exportLog = [];
} catch (e) {
importError.value = e.message;
} finally {
importing.value = false;
}
}
async function doExport() {
exportError.value = '';
exporting.value = true;
try {
const raw = await fetchScoreText(props.store.credentials);
const raw = await fetchScoreText();
props.store.rawScoreText = raw;
const model = props.store.scoreModel;
const { text: patched, log } = patchScore(
raw, model.instruments, model.bars, model.info, model.articles ?? [],
);
props.store.exportLog = log;
await putScoreText(patched, props.store.credentials);
await putScoreText(patched);
props.store.synthesisStatus = { frozen: false, currently_rendered_notes: 0, notes_in_total: 0 };
} catch (e) {
exportError.value = e.message;
@@ -81,6 +99,8 @@ export const PaneCP = {
}
}
onMounted(() => { if (props.importOnLoad) doImport(); });
return () => {
const store = props.store;
const model = store.scoreModel;
@@ -97,10 +117,10 @@ export const PaneCP = {
h('div', { class: 'se-cp-header' }, [
h('button', {
class: 'se-btn',
disabled: store.isDirty,
disabled: store.isDirty || importing.value,
title: store.isDirty ? 'Save or discard edits before re-importing' : 'Import from server',
onClick: props.onImportClick,
}, '→ Import'),
onClick: doImport,
}, importing.value ? 'Importing…' : '→ Import'),
h('span', { class: 'se-cp-title' },
model ? (model.info?.title ?? 'Untitled score') : 'No score loaded'),
model ? h('button', {
@@ -135,7 +155,8 @@ export const PaneCP = {
})
) : null,
// Export error
// Import / export errors
importError.value ? h('div', { class: 'se-error' }, importError.value) : null,
exportError.value ? h('div', { class: 'se-error' }, exportError.value) : null,
// Export log (shown after export, cleared on next import)