fix(06.2): resolve four sharing UX issues found in re-test UAT
- AccountView: remove hardcoded @ prefix so handle matches what share dialog expects
- documents store: set is_shared=true optimistically after successful share so badge shows without refetch
- GET /api/documents/{id}: allow recipients of an active share to view the document (was returning 404 for non-owners)
- ShareModal: move Share button to its own full-width row so it no longer overflows the input area
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -542,9 +542,20 @@ async def get_document(
|
||||
raise HTTPException(404, "Document not found")
|
||||
|
||||
doc = await session.get(Document, uid)
|
||||
if doc is None or doc.user_id != current_user.id:
|
||||
if doc is None:
|
||||
raise HTTPException(404, "Document not found")
|
||||
|
||||
if doc.user_id != current_user.id:
|
||||
# Allow recipients of an active share to view the document
|
||||
share_result = await session.execute(
|
||||
select(Share).where(
|
||||
Share.document_id == uid,
|
||||
Share.recipient_id == current_user.id,
|
||||
)
|
||||
)
|
||||
if share_result.scalar_one_or_none() is None:
|
||||
raise HTTPException(404, "Document not found")
|
||||
|
||||
meta = await storage.get_metadata(session, doc_id)
|
||||
if meta is None:
|
||||
raise HTTPException(404, "Document not found")
|
||||
|
||||
@@ -28,28 +28,30 @@
|
||||
</h2>
|
||||
|
||||
<!-- Handle input row -->
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
v-model="handle"
|
||||
type="text"
|
||||
placeholder="Enter username handle"
|
||||
class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
@keydown.enter="submitShare"
|
||||
/>
|
||||
<select
|
||||
v-model="permission"
|
||||
aria-label="Permission level"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 shrink-0"
|
||||
>
|
||||
<option value="view">Can view</option>
|
||||
<option value="edit">Can edit</option>
|
||||
</select>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
v-model="handle"
|
||||
type="text"
|
||||
placeholder="Enter username handle"
|
||||
class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
@keydown.enter="submitShare"
|
||||
/>
|
||||
<select
|
||||
v-model="permission"
|
||||
aria-label="Permission level"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 shrink-0"
|
||||
>
|
||||
<option value="view">Can view</option>
|
||||
<option value="edit">Can edit</option>
|
||||
</select>
|
||||
</div>
|
||||
<button
|
||||
@click="submitShare"
|
||||
:disabled="submitting || !handle.trim()"
|
||||
class="bg-indigo-600 hover:bg-indigo-700 text-white text-sm px-4 py-2 rounded-lg disabled:opacity-50 transition-colors shrink-0"
|
||||
class="w-full bg-indigo-600 hover:bg-indigo-700 text-white text-sm px-4 py-2 rounded-lg disabled:opacity-50 transition-colors"
|
||||
>
|
||||
<span v-if="submitting" class="flex items-center gap-1.5">
|
||||
<span v-if="submitting" class="flex items-center justify-center gap-1.5">
|
||||
<span class="animate-spin rounded-full border-2 border-current border-t-transparent w-3 h-3"></span>
|
||||
Sharing…
|
||||
</span>
|
||||
|
||||
@@ -157,7 +157,10 @@ export const useDocumentsStore = defineStore('documents', () => {
|
||||
}
|
||||
|
||||
async function shareDocument(docId, recipientHandle, permission = 'view') {
|
||||
try { return await api.createShare(docId, recipientHandle, permission) } catch (e) { throw e }
|
||||
const result = await api.createShare(docId, recipientHandle, permission)
|
||||
const doc = documents.value.find(d => d.id === docId)
|
||||
if (doc) doc.is_shared = true
|
||||
return result
|
||||
}
|
||||
|
||||
async function revokeShare(shareId) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<h3 class="font-semibold text-gray-800 mb-4">Account information</h3>
|
||||
<div class="space-y-2 text-sm text-gray-700">
|
||||
<div><span class="text-gray-500">Email:</span> {{ authStore.user?.email }}</div>
|
||||
<div><span class="text-gray-500">Username:</span> @{{ authStore.user?.handle }}</div>
|
||||
<div><span class="text-gray-500">Username:</span> {{ authStore.user?.handle }}</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-gray-500">Role:</span>
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user