2 Commits

2 changed files with 65 additions and 16 deletions
+19 -14
View File
@@ -431,22 +431,32 @@ window.__ModuleLoader__.load({
)
: null
const workspacePaths = workspaces.map((item) => item.path).filter(Boolean)
const workspaceOptions =
workspace && !workspacePaths.includes(workspace) ? [workspace, ...workspacePaths] : workspacePaths
const workspaceTitles = Object.fromEntries(workspaces.map((item) => [item.path, item.title]))
const workspaceRow = h(
'div',
{ style: { display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 12, marginTop: 16 } },
h(
Field,
{ label: DICTS.zh.workspace, hint: DICTS.zh.workspaceHint },
h('input', {
style: inputStyle,
value: workspace,
list: 'abap-adt-workspaces',
onChange: (event) => setWorkspace(event.target.value),
onBlur: () => {
if (workspace && workspace !== file?.path?.replace(/[\\/]\.dsh-abap-adt[\\/].*$/, '')) load(workspace)
h(
'select',
{
style: inputStyle,
value: workspace,
onChange: (event) => {
const next = event.target.value
setWorkspace(next)
if (next) load(next)
},
},
placeholder: 'D:\\AIagent\\SAP',
}),
workspaceOptions.map((path) => {
const title = workspaceTitles[path]
return h('option', { key: path, value: path }, title && title !== path ? title + ' — ' + path : path)
}),
),
),
h(
Field,
@@ -457,11 +467,6 @@ window.__ModuleLoader__.load({
file?.path ? `${file.path}${file.exists ? '' : DICTS.zh.notExists}` : DICTS.zh.never,
),
),
h(
'datalist',
{ id: 'abap-adt-workspaces' },
workspaces.map((item) => h('option', { key: item.id || item.path, value: item.path }, item.title)),
),
)
const destinationCards = destinations.length
+46 -2
View File
@@ -16,7 +16,7 @@
* the DSH credential service (falling back to the process environment).
*/
import { existsSync, readdirSync } from 'node:fs'
import { existsSync, readdirSync, statSync } from 'node:fs'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { request as httpRequest } from 'node:http'
import { request as httpsRequest } from 'node:https'
@@ -508,8 +508,52 @@ export function apply(ctx, config) {
}
}
/**
* The workspace whose destinations file was written most recently. An empty
* destinations list (a scratch config, or one where every system was removed)
* loses to any workspace that still lists systems, so the settings page never
* opens on an empty page while a usable config exists elsewhere.
*/
async function lastModifiedWorkspace() {
let best
let bestTime = -Infinity
let any
let anyTime = -Infinity
for (const row of listWorkspaces()) {
if (!row.path) continue
for (const fileName of FILE_NAMES) {
const candidate = join(row.path, CONFIG_DIR, fileName)
let mtimeMs
try {
mtimeMs = statSync(candidate).mtimeMs
} catch {
continue
}
if (mtimeMs > anyTime) {
anyTime = mtimeMs
any = row.path
}
if (mtimeMs <= bestTime) continue
try {
const parsed = await parseDestinations(await readFile(candidate, 'utf8'))
if (!normalizeDestinations(parsed.destinations).length) continue
} catch {
continue
}
bestTime = mtimeMs
best = row.path
}
}
return best || any
}
async function stateOf({ sessionId, workspace }) {
const cwd = workspace || resolveCwd(sessionId) || listWorkspaces()[0]?.path || process.cwd()
const cwd =
workspace ||
resolveCwd(sessionId) ||
(await lastModifiedWorkspace()) ||
listWorkspaces()[0]?.path ||
process.cwd()
const file = existingWorkspaceFile(cwd)
let raw = ''
let exists = false