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
73 lines
2.7 KiB
JavaScript
73 lines
2.7 KiB
JavaScript
import { h, ref, computed, watch } from 'vue';
|
|
import { PaneCP } from './PaneCP.js';
|
|
import { PaneFO } from './PaneFO.js';
|
|
import { PaneSubObjects } from './PaneSubObjects.js';
|
|
import { getKindGroups, KIND_LABEL } from '../subobject-kinds.js';
|
|
|
|
const FIXED_PANES = [
|
|
{ id: 'cp', label: 'CP', title: 'Current position' },
|
|
{ id: 'fo', label: 'FO', title: 'Focused object' },
|
|
];
|
|
|
|
export const AppShell = {
|
|
props: ['store', 'importOnLoad'],
|
|
setup(props) {
|
|
const activePane = ref('cp');
|
|
|
|
function focusedNode() {
|
|
const fp = props.store.focusPath;
|
|
return fp.length ? fp[fp.length - 1] : props.store.scoreModel;
|
|
}
|
|
|
|
const subPanes = computed(() => getKindGroups(focusedNode()).map(g => ({
|
|
id: `sub:${g.kind}`,
|
|
kind: g.kind,
|
|
label: KIND_LABEL[g.kind] ?? g.kind.slice(0, 2).toUpperCase(),
|
|
title: g.kind,
|
|
})));
|
|
|
|
const panes = computed(() => [...FIXED_PANES, ...subPanes.value]);
|
|
|
|
// If active pane disappears after focus change, drop back to FO.
|
|
watch(panes, ps => {
|
|
if (!ps.some(p => p.id === activePane.value)) activePane.value = 'fo';
|
|
});
|
|
|
|
return () => {
|
|
const store = props.store;
|
|
const ap = activePane.value;
|
|
|
|
const subPaneNodes = subPanes.value.map(p =>
|
|
h('div', { key: p.id, class: ['se-pane', ap === p.id ? 'active' : null] },
|
|
h(PaneSubObjects, { store, kind: p.kind, onFocusFO: () => { activePane.value = 'fo'; } })));
|
|
|
|
return h('div', { class: 'se-shell' }, [
|
|
h('div', { class: 'se-pane-area' }, [
|
|
h('div', { class: ['se-pane', ap === 'cp' ? 'active' : null] },
|
|
h(PaneCP, {
|
|
store,
|
|
importOnLoad: props.importOnLoad,
|
|
onFocusFO: () => { activePane.value = 'fo'; },
|
|
})),
|
|
h('div', { class: ['se-pane', ap === 'fo' ? 'active' : null] },
|
|
h(PaneFO, { store })),
|
|
...subPaneNodes,
|
|
]),
|
|
|
|
h('div', { class: 'se-handle-bar' }, panes.value.map(p =>
|
|
h('button', {
|
|
key: p.id,
|
|
class: ['se-handle', ap === p.id ? 'active' : null],
|
|
title: p.title,
|
|
onClick: () => { activePane.value = p.id; },
|
|
}, p.label)
|
|
)),
|
|
|
|
store.errorMessage
|
|
? h('div', { class: 'se-error', style: 'margin:0' }, store.errorMessage)
|
|
: null,
|
|
]);
|
|
};
|
|
},
|
|
};
|