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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user