Skip to content

Commit f48ecd0

Browse files
authored
update: The interface for ordinary users to view resources has been replaced (#2018)
1 parent d99b088 commit f48ecd0

File tree

4 files changed

+74
-17
lines changed

4 files changed

+74
-17
lines changed

moon/apps/web/components/NoteEditor/NoteContent.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,13 @@ export const NoteContent = memo(
140140
})
141141

142142
return (
143-
<div ref={containerRef} className={cn('relative', { 'opacity-50': isSyncError })}>
143+
<div
144+
ref={containerRef}
145+
className={cn('relative', {
146+
'opacity-50': isSyncError,
147+
'[&_.ProseMirror]:cursor-default [&_.ProseMirror]:caret-transparent': editable !== 'all'
148+
})}
149+
>
144150
<LayeredHotkeys
145151
keys={ADD_ATTACHMENT_SHORTCUT}
146152
callback={() => {

moon/apps/web/components/NoteView/index.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { SubjectEspcapeLayeredHotkeys } from '@/components/Subject'
2828
import { ProjectAccessoryBreadcrumbIcon } from '@/components/Titlebar/BreadcrumbPageIcons'
2929
import { BreadcrumbLabel } from '@/components/Titlebar/BreadcrumbTitlebar'
3030
import { useScope } from '@/contexts/scope'
31+
import { useGetNotesPermissions } from '@/hooks/admin/useGetNotesPermissions'
3132
import { useCreateNoteView } from '@/hooks/useCreateNoteView'
3233
import { useGetNote } from '@/hooks/useGetNote'
3334
import { useGetNoteComments } from '@/hooks/useGetNoteComments'
@@ -85,6 +86,15 @@ function InnerNoteView({ note }: { note: Note }) {
8586
useCreateLingerNoteView(note.id, !!note)
8687
useLiveNoteUpdates(note)
8788

89+
// Get permissions for this note
90+
const { data: notesPermissions } = useGetNotesPermissions({
91+
notes: [note],
92+
enabled: true
93+
})
94+
95+
const permission = notesPermissions?.[note.id]
96+
const hasWritePermission = permission?.hasWrite ?? note.viewer_can_edit
97+
8898
// prefetch comments
8999
useGetNoteComments({ noteId: note.id })
90100
useGetNoteTimelineEvents({ noteId: note.id, enabled: true })
@@ -108,6 +118,7 @@ function InnerNoteView({ note }: { note: Note }) {
108118
</InboxSplitViewTitleBar>
109119

110120
<PublicVisibilityBanner note={note} />
121+
{!hasWritePermission && note.viewer_can_edit && <NoWritePermissionBanner />}
111122

112123
<ScrollableContainer id='note-scroll-container'>
113124
<div
@@ -118,7 +129,7 @@ function InnerNoteView({ note }: { note: Note }) {
118129
<NoteEditor
119130
// key by note.id in order to reset tiptap editor state
120131
key={note.id}
121-
note={note}
132+
note={{ ...note, viewer_can_edit: hasWritePermission }}
122133
/>
123134
)}
124135
</div>
@@ -146,6 +157,17 @@ function PublicVisibilityBanner({ note }: { note: Note }) {
146157
)
147158
}
148159

160+
function NoWritePermissionBanner() {
161+
return (
162+
<div className='flex w-full items-center justify-center gap-3 border-b border-amber-100/60 bg-amber-50 px-4 py-2.5 text-sm text-amber-700 dark:border-amber-900/35 dark:bg-amber-900/20 dark:text-amber-200'>
163+
<LockIcon size={18} className='flex-none' strokeWidth='2' />
164+
<UIText weight='font-medium' inherit>
165+
You have read-only access to this document
166+
</UIText>
167+
</div>
168+
)
169+
}
170+
149171
function useCreateLingerNoteView(noteId: string, isLoaded: boolean) {
150172
const { mutate: create } = useCreateNoteView()
151173
const hasMarkedSeen = useRef(false)

moon/apps/web/components/NotesIndex/NoteRow.tsx

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { memo } from 'react'
22
import { format } from 'date-fns'
33

44
import { Note } from '@gitmono/types'
5-
import { GlobeIcon, HighlightedCommandItem, NoteFilledIcon, Tooltip, UIText } from '@gitmono/ui'
5+
import { GlobeIcon, HighlightedCommandItem, LockIcon, NoteFilledIcon, Tooltip, UIText } from '@gitmono/ui'
66
import { cn } from '@gitmono/ui/src/utils'
77

88
import { NoteOverflowMenu } from '@/components/NoteOverflowMenu'
@@ -41,7 +41,7 @@ export const NoteRow = memo(({ note, display = 'default', hideProject = false, p
4141
const content = (
4242
<div
4343
className={cn('relative flex items-center gap-3 px-3 py-2.5', {
44-
'cursor-not-allowed opacity-40': isDisabled
44+
'cursor-not-allowed opacity-50': isDisabled
4545
})}
4646
>
4747
<NoteOverflowMenu type='context' note={note}>
@@ -53,25 +53,36 @@ export const NoteRow = memo(({ note, display = 'default', hideProject = false, p
5353
/>
5454
</NoteOverflowMenu>
5555

56-
<div className='flex h-11 w-11 items-center justify-center rounded-full bg-blue-50 text-blue-500 dark:bg-blue-900/50'>
57-
<NoteFilledIcon size={24} />
56+
<div
57+
className={cn(
58+
'flex h-11 w-11 items-center justify-center rounded-full',
59+
isDisabled
60+
? 'bg-gray-100 text-gray-400 dark:bg-gray-800 dark:text-gray-600'
61+
: 'bg-blue-50 text-blue-500 dark:bg-blue-900/50'
62+
)}
63+
>
64+
{isDisabled ? <LockIcon size={24} strokeWidth='2' /> : <NoteFilledIcon size={24} />}
5865
</div>
5966

6067
<UIText weight='font-medium' className='break-anywhere line-clamp-1 max-w-lg'>
6168
{note.title || 'Untitled'}
6269
</UIText>
63-
64-
{isDisabled && <span className='text-xs text-gray-400'>🔒</span>}
6570
</div>
6671
)
6772

68-
return isDisabled ? <Tooltip label='You do not have permission to view this document'>{content}</Tooltip> : content
73+
return isDisabled ? (
74+
<Tooltip label='You do not have permission to view this document' side='top' align='start'>
75+
{content}
76+
</Tooltip>
77+
) : (
78+
content
79+
)
6980
}
7081

7182
const content = (
7283
<div
7384
className={cn('relative flex items-center gap-3 px-3 py-2.5', {
74-
'cursor-not-allowed opacity-40': isDisabled
85+
'cursor-not-allowed opacity-50': isDisabled
7586
})}
7687
>
7788
<NoteOverflowMenu type='context' note={note}>
@@ -84,7 +95,13 @@ export const NoteRow = memo(({ note, display = 'default', hideProject = false, p
8495
</NoteOverflowMenu>
8596

8697
<div className='flex flex-1 items-center gap-3'>
87-
<NotePrivacyIndicator note={note} />
98+
{isDisabled ? (
99+
<div className='flex h-5 w-5 items-center justify-center rounded bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400'>
100+
<LockIcon size={14} strokeWidth='2.5' />
101+
</div>
102+
) : (
103+
<NotePrivacyIndicator note={note} />
104+
)}
88105

89106
<ViewerFollowUpTag followUps={note.follow_ups} />
90107

@@ -97,8 +114,6 @@ export const NoteRow = memo(({ note, display = 'default', hideProject = false, p
97114
{format(note.created_at, 'MMM d, yyyy')}
98115
</UIText>
99116
)}
100-
101-
{isDisabled && <span className='text-xs text-gray-400'>🔒</span>}
102117
</div>
103118

104119
<div className='flex items-center gap-1'>
@@ -114,6 +129,12 @@ export const NoteRow = memo(({ note, display = 'default', hideProject = false, p
114129
</div>
115130
)
116131

117-
return isDisabled ? <Tooltip label='You do not have permission to view this document'>{content}</Tooltip> : content
132+
return isDisabled ? (
133+
<Tooltip label='You do not have permission to view this document' side='top' align='start'>
134+
{content}
135+
</Tooltip>
136+
) : (
137+
content
138+
)
118139
})
119140
NoteRow.displayName = 'NoteRow'

moon/apps/web/hooks/admin/useGetNotesPermissions.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@ export function useGetNotesPermissions({ notes, enabled = true }: UseGetNotesPer
4848
// Batch query permissions for all notes
4949
const permissionsPromises = notes.map(async (note) => {
5050
try {
51-
const response = await legacyApiClient.v1
52-
.getApiAdminUsersPermissionsByResourceId()
53-
.request(currentUser?.username || '', 'note', note.id)
51+
let response
52+
53+
if (isSystemAdmin) {
54+
// Admin users: use admin endpoint
55+
response = await legacyApiClient.v1
56+
.getApiAdminUsersPermissionsByResourceId()
57+
.request(currentUser?.username || '', 'note', note.id)
58+
} else {
59+
// Regular users: use /me endpoint
60+
response = await legacyApiClient.v1.getApiPermissionsMeByResourceId().request('note', note.id)
61+
}
5462

5563
if (response?.data) {
5664
return {

0 commit comments

Comments
 (0)