Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release/1.7.0
Browse files Browse the repository at this point in the history
* origin/master:
  fix: Make "…" click area bigger
  feat: Allows to turn the editor read-only
  • Loading branch information
edas committed Jan 31, 2020
2 parents 3d59376 + b7be7b9 commit bb4efac
Show file tree
Hide file tree
Showing 7 changed files with 422 additions and 115 deletions.
4 changes: 2 additions & 2 deletions src/components/notes/List/NoteRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ const NoteRow = ({ note, f, t, client, breakpoints: { isMobile } }) => {
<TableCell className={styles.tableCell}></TableCell>
<TableCell className={styles.tableCell}>
<span ref={menuTriggerRef}>
<IconButton>
<Icon onClick={openMenu} icon="dots" />
<IconButton onClick={openMenu}>
<Icon icon="dots" />
</IconButton>
</span>
</TableCell>
Expand Down
37 changes: 29 additions & 8 deletions src/components/notes/editor-view.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React, { useCallback, useRef, useEffect } from 'react'
import React, { useCallback, useRef, useEffect, useMemo } from 'react'

import { Editor, WithEditorActions } from '@atlaskit/editor-core'

import { MainTitle } from 'cozy-ui/react/Text'
import Textarea from 'cozy-ui/react/Textarea'
import { translate } from 'cozy-ui/react/I18n'
import { useI18n } from 'cozy-ui/react/I18n'
import useEventListener from 'cozy-ui/react/hooks/useEventListener'

import editorConfig from 'components/notes/editor_config'
import HeaderMenu from 'components/header_menu'
import styles from 'components/notes/editor-view.styl'

function updateTextareaHeight(target) {
target.style.height = `${target.scrollHeight}px`
if (target) target.style.height = `${target.scrollHeight}px`
}

const nullCallback = () => {}
Expand All @@ -28,8 +28,9 @@ function EditorView(props) {
leftComponent,
rightComponent,
onContentChange,
t
readOnly
} = props
const { t } = useI18n()

const titleEl = useRef(null)

Expand All @@ -42,6 +43,24 @@ function EditorView(props) {
[onTitleChange]
)

// put the provider in readonly mode if requested and react to changes of values
useMemo(() => collabProvider && collabProvider.setReadOnly(!!readOnly), [
readOnly,
collabProvider
])

const collabEdit = useMemo(
() =>
collabProvider && {
useNativePlugin: true,
provider: Promise.resolve(collabProvider),
inviteToEditHandler: () => undefined,
isInviteToEditButtonSelected: false,
userId: collabProvider.serviceClient.getSessionId()
},
[collabProvider]
)

useEffect(() => updateTextareaHeight(titleEl.current), [])

useEventListener(titleEl.current, 'blur', onTitleBlur)
Expand All @@ -56,23 +75,25 @@ function EditorView(props) {
/>
<section className="note-editor-container">
<Editor
collabEdit={collabProvider}
disabled={collabProvider ? false : readOnly}
collabEdit={collabEdit}
onChange={onContentChange || nullCallback}
defaultValue={defaultValue}
{...editorConfig}
appearance="full-page"
placeholder={t('Notes.EditorView.main_placeholder')}
shouldFocus={true}
shouldFocus={!readOnly}
contentComponents={
<WithEditorActions
render={() => (
<MainTitle tag="h1" className="note-title">
<Textarea
ref={titleEl}
rows="1"
readOnly={!!readOnly}
fullwidth={true}
value={title}
onChange={onTitleEvent}
onChange={readOnly ? nullCallback : onTitleEvent}
placeholder={defaultTitle}
className="note-title-input"
/>
Expand All @@ -86,4 +107,4 @@ function EditorView(props) {
)
}

export default translate()(EditorView)
export default EditorView
154 changes: 154 additions & 0 deletions src/components/notes/editor-view.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import React from 'react'
import { I18n } from 'cozy-ui/react/I18n'
import { mount } from 'enzyme'

import EditorView from './editor-view'
import CollabProvider from 'lib/collab/provider'
import en from '../../locales/en.json'

import { MainTitle } from 'cozy-ui/react/Text'
import Textarea from 'cozy-ui/react/Textarea'

// eslint-disable-next-line no-unused-vars
import { Editor, WithEditorActions } from '@atlaskit/editor-core'
jest.mock('@atlaskit/editor-core', () => ({
Editor: function Editor(props) {
return (
<div>
{props.contentComponents}
{props.children}
</div>
)
},
WithEditorActions: function WithEditorActions(props) {
return (
<div>
{props.render()}
{props.children}
</div>
)
}
}))

function setupCollabProvider() {
const noteId = 'myDocId'
const version = 96
const channel = {
on: jest.fn(),
connect: jest.fn(),
sendSteps: jest.fn(),
sendTelepointer: jest.fn(),
getSteps: jest.fn()
}
const service = {
getSessionId: jest.fn(),
getUserId: jest.fn(),
pushSteps: jest.fn(),
onStepsCreated: jest.fn(),
onTelepointerUpdated: jest.fn(),
join: jest.fn(),
getSteps: jest.fn(),
pushTelepointer: jest.fn()
}
const config = { noteId, version, channel }
return new CollabProvider(config, service)
}

function mountEditorView({ readOnly, collabProvider }) {
return mount(
<EditorView
readOnly={readOnly}
collabProvider={collabProvider}
defaultTitle="placeholder"
defaultValue={{ doc: {}, version: 42 }}
title="title"
/>,
{
wrappingComponent: I18n,
wrappingComponentProps: {
lang: 'en',
dictRequire: () => en
}
}
)
}

describe('EditorView', () => {
describe('readOnly', () => {
describe('when true', () => {
const readOnly = true
it('should have a readonly title', async () => {
const collabProvider = setupCollabProvider()
const editorView = mountEditorView({ collabProvider, readOnly })
const title = editorView
.find(MainTitle)
.first()
.find(Textarea)
.first()
expect(title.prop('readOnly')).toBeTruthy()
})

it('should not focus the editor', async () => {
const collabProvider = setupCollabProvider()
const editorView = mountEditorView({ collabProvider, readOnly })
const editor = editorView.find(Editor).first()
expect(editor.prop('shouldFocus')).toBeFalsy()
})

describe('with a collabProvider', () => {
it('should set the provider readonly', async () => {
const collabProvider = setupCollabProvider()
mountEditorView({ collabProvider, readOnly })
expect(collabProvider.isReadOnly()).toBeTruthy()
})
})

describe('without a collabProvider', () => {
it('should disable the editor', async () => {
const collabProvider = undefined
const editorView = mountEditorView({ collabProvider, readOnly })
const editor = editorView.find(Editor).first()
expect(editor.prop('disabled')).toBeTruthy()
})
})
})

describe('when false', () => {
const readOnly = false
it('should not have a readonly title', async () => {
const collabProvider = setupCollabProvider()
const editorView = mountEditorView({ collabProvider, readOnly })
const title = editorView
.find(MainTitle)
.first()
.find(Textarea)
.first()
expect(title.prop('readOnly')).toBeFalsy()
})

it('should focus the editor', async () => {
const collabProvider = setupCollabProvider()
const editorView = mountEditorView({ collabProvider, readOnly })
const editor = editorView.find(Editor).first()
expect(editor.prop('shouldFocus')).toBeTruthy()
})

describe('with a collabProvider', () => {
it('should not set the provider readonly', async () => {
const collabProvider = setupCollabProvider()
mountEditorView({ collabProvider, readOnly })
expect(collabProvider.isReadOnly()).toBeFalsy()
})
})

describe('without a collabProvider', () => {
it('should not disable the editor', async () => {
const collabProvider = undefined
const editorView = mountEditorView({ collabProvider, readOnly })
const editor = editorView.find(Editor).first()
expect(editor.prop('disabled')).toBeFalsy()
})
})
})
})
})
Loading

0 comments on commit bb4efac

Please sign in to comment.