feat(12-03): connection-ID routing, rename, session folder memory, thin views

- Route /cloud/:connectionId/:folderId replaces /cloud/:provider/:folderId
- api/cloud.js: getCloudFoldersByConnectionId + renameCloudConnection
- cloudConnections store: rename, selectConnection, setBrowseState, defaultDisplayName, session storage helpers
- CloudStorageView: thin — passes connectionRoots to StorageBrowser
- CloudFolderView: thin — uses connectionId param, never provider slug
- SettingsCloudTab: inline rename input for each active connection
- 27 tests pass: store, view, settings
This commit is contained in:
curo1305
2026-06-18 23:25:29 +02:00
parent 6f0ecfa39b
commit bf9af11274
10 changed files with 594 additions and 91 deletions
@@ -60,8 +60,33 @@
<!-- ACTIVE -->
<template v-else-if="connectionFor(provider.key)?.status === 'ACTIVE'">
<!-- Rename display name -->
<template v-if="renamingId === connectionFor(provider.key)?.id">
<input
v-model="renameValue"
class="border border-gray-300 rounded-lg px-2 py-1 text-sm w-40 focus:outline-none focus:ring-2 focus:ring-indigo-500"
@keydown.enter="submitRename(connectionFor(provider.key)?.id)"
@keydown.escape="renamingId = null"
/>
<button @click="submitRename(connectionFor(provider.key)?.id)"
class="text-sm px-2 py-1 text-indigo-600 hover:underline font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1 rounded">
Save
</button>
<button @click="renamingId = null"
class="text-sm px-2 py-1 text-gray-500 hover:text-gray-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1 rounded">
Cancel
</button>
</template>
<button
v-if="!OAUTH_PROVIDERS.has(provider.key) && confirmRemoveId !== connectionFor(provider.key)?.id"
v-else-if="confirmRemoveId !== connectionFor(provider.key)?.id"
@click="startRename(connectionFor(provider.key))"
class="text-sm px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 active:bg-gray-100 text-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1"
title="Rename connection"
>
Rename
</button>
<button
v-if="!OAUTH_PROVIDERS.has(provider.key) && confirmRemoveId !== connectionFor(provider.key)?.id && renamingId !== connectionFor(provider.key)?.id"
@click="handleEdit(provider)"
class="text-sm px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 active:bg-gray-100 text-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1"
>
@@ -216,6 +241,9 @@ const editingConnection = ref(null)
const confirmRemoveId = ref(null)
const showDisconnectAll = ref(false)
const oauthError = ref('')
const renamingId = ref(null)
const renameValue = ref('')
const renameError = ref('')
onMounted(() => {
store.fetchConnections()
@@ -297,4 +325,22 @@ async function handleDisconnectAll() {
async function handleConnected() {
await store.fetchConnections()
}
function startRename(connection) {
if (!connection) return
renamingId.value = connection.id
renameValue.value = connection.display_name || ''
renameError.value = ''
}
async function submitRename(id) {
if (!id) return
renameError.value = ''
try {
await store.rename(id, renameValue.value)
renamingId.value = null
} catch (e) {
renameError.value = e.message || 'Failed to rename connection'
}
}
</script>