chore: vault member permissions (#2509)
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
SNNote,
|
||||
NoteType,
|
||||
PayloadEmitSource,
|
||||
VaultServiceInterface,
|
||||
} from '@standardnotes/snjs'
|
||||
import NoteView from './NoteView'
|
||||
import { NoteViewController } from './Controller/NoteViewController'
|
||||
@@ -19,6 +20,7 @@ describe('NoteView', () => {
|
||||
let application: WebApplication
|
||||
|
||||
let notesController: NotesController
|
||||
let vaults: VaultServiceInterface
|
||||
|
||||
const createNoteView = () =>
|
||||
new NoteView({
|
||||
@@ -36,9 +38,13 @@ describe('NoteView', () => {
|
||||
notesController.getSpellcheckStateForNote = jest.fn()
|
||||
notesController.getEditorWidthForNote = jest.fn()
|
||||
|
||||
vaults = {} as jest.Mocked<VaultServiceInterface>
|
||||
vaults.getItemVault = jest.fn().mockReturnValue(undefined)
|
||||
|
||||
application = {
|
||||
notesController,
|
||||
noteViewController,
|
||||
vaults,
|
||||
} as unknown as jest.Mocked<WebApplication>
|
||||
|
||||
application.hasProtectionSources = jest.fn().mockReturnValue(true)
|
||||
|
||||
@@ -68,6 +68,7 @@ type State = {
|
||||
isDesktop?: boolean
|
||||
editorLineWidth: EditorLineWidth
|
||||
noteLocked: boolean
|
||||
readonly: boolean
|
||||
noteStatus?: NoteStatus
|
||||
saveError?: boolean
|
||||
showProtectedWarning: boolean
|
||||
@@ -116,6 +117,8 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
|
||||
this.debounceReloadEditorComponent = debounce(this.debounceReloadEditorComponent.bind(this), 25)
|
||||
|
||||
const itemVault = this.application.vaults.getItemVault(this.controller.item)
|
||||
|
||||
this.state = {
|
||||
availableStackComponents: [],
|
||||
editorStateDidLoad: false,
|
||||
@@ -124,6 +127,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
isDesktop: isDesktopApplication(),
|
||||
noteStatus: undefined,
|
||||
noteLocked: this.controller.item.locked,
|
||||
readonly: itemVault ? this.application.vaultUsers.isCurrentUserReadonlyVaultMember(itemVault) : false,
|
||||
showProtectedWarning: false,
|
||||
spellcheck: true,
|
||||
stackComponentViewers: [],
|
||||
@@ -855,6 +859,13 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
/>
|
||||
)}
|
||||
|
||||
{this.state.readonly && (
|
||||
<div className="bg-warning-faded flex items-center px-3.5 py-2 text-sm text-accessory-tint-3">
|
||||
<Icon type="pencil-off" className="mr-3" />
|
||||
You don't have permission to edit this note
|
||||
</div>
|
||||
)}
|
||||
|
||||
{this.state.noteLocked && (
|
||||
<EditingDisabledBanner
|
||||
onClick={() => this.application.notesController.setLockSelectedNotes(!this.state.noteLocked)}
|
||||
@@ -878,7 +889,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
<div className="title flex-grow overflow-auto">
|
||||
<input
|
||||
className="input text-lg"
|
||||
disabled={this.state.noteLocked}
|
||||
disabled={this.state.noteLocked || this.state.readonly}
|
||||
id={ElementIds.NoteTitleEditor}
|
||||
onChange={this.onTitleChange}
|
||||
onFocus={(event) => {
|
||||
@@ -911,18 +922,22 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
)}
|
||||
{renderHeaderOptions && (
|
||||
<div className="note-view-options-buttons flex items-center gap-3">
|
||||
<LinkedItemsButton
|
||||
linkingController={this.application.linkingController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
noteViewController={this.controller}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
{!this.state.readonly && (
|
||||
<>
|
||||
<LinkedItemsButton
|
||||
linkingController={this.application.linkingController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
noteViewController={this.controller}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<NotesOptionsPanel
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
@@ -934,7 +949,11 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
<CollaborationInfoHUD item={this.note} />
|
||||
</div>
|
||||
<div className="hidden md:block">
|
||||
<LinkedItemBubblesContainer item={this.note} linkingController={this.application.linkingController} />
|
||||
<LinkedItemBubblesContainer
|
||||
item={this.note}
|
||||
linkingController={this.application.linkingController}
|
||||
readonly={this.state.readonly}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -961,6 +980,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
componentViewer={this.state.editorComponentViewer}
|
||||
onLoad={this.onEditorComponentLoad}
|
||||
requestReload={this.editorComponentViewerRequestsReload}
|
||||
readonly={this.state.readonly}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -971,7 +991,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
spellcheck={this.state.spellcheck}
|
||||
ref={this.setPlainEditorRef}
|
||||
controller={this.controller}
|
||||
locked={this.state.noteLocked}
|
||||
locked={this.state.noteLocked || this.state.readonly}
|
||||
onFocus={this.onPlainFocus}
|
||||
onBlur={this.onPlainBlur}
|
||||
/>
|
||||
@@ -986,6 +1006,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
filesController={this.application.filesController}
|
||||
spellcheck={this.state.spellcheck}
|
||||
controller={this.controller}
|
||||
readonly={this.state.readonly}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user