From 921a1369b24b20bc5a566d83e558e4f04e036af2 Mon Sep 17 00:00:00 2001 From: kyeongsoosoo Date: Tue, 19 Apr 2022 01:37:06 +0900 Subject: [PATCH 1/7] fix undo/redo/cut --- .../markdownEditorInput.tsx | 69 +++++++++---------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx index 6bfee2d55..f687e01e5 100644 --- a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx +++ b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx @@ -10,7 +10,7 @@ import createMentionPlugin, { import '@draft-js-plugins/mention/lib/plugin.css' import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js' import React, { - ReactElement, useCallback, useEffect, + ReactElement, useCallback, useMemo, useRef, useState, } from 'react' @@ -46,24 +46,7 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return EditorState.moveSelectionToEnd(state) } - const [editorState, setEditorState] = useState(() => { - return generateEditorState(initialText) - }) - - const [initialTextCache, setInitialTextCache] = useState(initialText) - - // avoiding stale closure - useEffect(() => { - // only change editor state when initialText actually changes from one defined value to another. - // This is needed to make the mentions plugin work. For some reason, if we don't check - // for this if condition here, mentions don't work. I suspect it's because without - // the in condition, we're changing editor state twice during component initialization - // and for some reason it causes mentions to not show up. - if (initialText && initialText !== initialTextCache) { - setEditorState(generateEditorState(initialText || '')) - setInitialTextCache(initialText) - } - }, [initialText]) + const [editorState, setEditorState] = useState(() => generateEditorState(initialText)) const [isMentionPopoverOpen, setIsMentionPopoverOpen] = useState(false) const [isEmojiPopoverOpen, setIsEmojiPopoverOpen] = useState(false) @@ -87,16 +70,13 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return {plugins, MentionSuggestions, EmojiSuggestions} }, []) - useEffect(() => { - if (isEditing) { - if (initialText === '') { - setEditorState(EditorState.createEmpty()) - } else { - setEditorState(EditorState.moveSelectionToEnd(editorState)) - } - setTimeout(() => ref.current?.focus(), 200) - } - }, [isEditing, initialText]) + const onEditorStateChange = useCallback((newEditorState: EditorState) => { + // newEditorState. + const newText = newEditorState.getCurrentContent().getPlainText() + + onChange && onChange(newText) + setEditorState(newEditorState) + }, [onChange]) const customKeyBindingFn = useCallback((e: React.KeyboardEvent) => { if (isMentionPopoverOpen || isEmojiPopoverOpen) { @@ -107,14 +87,36 @@ const MarkdownEditorInput = (props: Props): ReactElement => { return 'editor-blur' } + if(getDefaultKeyBinding(e) === 'undo'){ + return 'editor-undo' + } + + if(getDefaultKeyBinding(e) === 'redo'){ + return 'editor-redo' + } + return getDefaultKeyBinding(e as any) }, [isEmojiPopoverOpen, isMentionPopoverOpen]) - const handleKeyCommand = useCallback((command: string): DraftHandleValue => { + const handleKeyCommand = useCallback((command: string, currentState: EditorState): DraftHandleValue => { if (command === 'editor-blur') { ref.current?.blur() return 'handled' } + + if(command === 'editor-redo'){ + const selectionRemovedState = EditorState.redo(currentState) + onEditorStateChange(EditorState.redo(selectionRemovedState)) + + return 'handled' + } + + if(command === 'editor-undo'){ + const selectionRemovedState = EditorState.undo(currentState) + onEditorStateChange(EditorState.undo(selectionRemovedState)) + + return 'handled' + } return 'not-handled' }, []) @@ -124,13 +126,6 @@ const MarkdownEditorInput = (props: Props): ReactElement => { onBlur && onBlur(text) }, [editorState, onBlur]) - const onEditorStateChange = useCallback((newEditorState: EditorState) => { - const newText = newEditorState.getCurrentContent().getPlainText() - - onChange && onChange(newText) - setEditorState(newEditorState) - }, [onChange]) - const onMentionPopoverOpenChange = useCallback((open: boolean) => { setIsMentionPopoverOpen(open) }, []) From c3f3587eb91bc9612a9786a038800a723a1ec100 Mon Sep 17 00:00:00 2001 From: kyeongsoosoo Date: Wed, 20 Apr 2022 17:43:05 +0900 Subject: [PATCH 2/7] add cypress test --- webapp/cypress/integration/createBoard.ts | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/webapp/cypress/integration/createBoard.ts b/webapp/cypress/integration/createBoard.ts index 6ade166cf..512ed5c62 100644 --- a/webapp/cypress/integration/createBoard.ts +++ b/webapp/cypress/integration/createBoard.ts @@ -183,4 +183,37 @@ describe('Create and delete board / card', () => { cy.get('.Kanban').invoke('scrollLeft').should('equal', 0) }) + + it('GH-2520 make cut/undo/redo work in comments', () => { + // Visit a page and create new empty board + cy.visit('/') + cy.uiCreateEmptyBoard() + + // Create card + cy.log('**Create card**') + cy.get('.ViewHeader').contains('New').click() + cy.get('.CardDetail').should('exist') + + cy.log('**Add comment**') + cy.get('.CommentsList').findAllByTestId('preview-element').click() + + cy.get('.MarkdownEditorInput').should('exist'). + type('Test Text') + + cy.log('**Cut comment**') + cy.get('.CommentsList .MarkdownEditorInput'). + type('{selectAll}'). + trigger('cut'). + should('have.text', '') + + cy.log('**Undo comment**') + cy.get('.CommentsList .MarkdownEditorInput'). + type('{meta+z}'). + should('have.text', 'Test Text') + + cy.log('**Redo comment**') + cy.get('.CommentsList .MarkdownEditorInput'). + type('{shift+meta+z}'). + should('have.text', '') + }) }) From 872bc61defea69726b1145d95d4104c731a312df Mon Sep 17 00:00:00 2001 From: kyeongsoosoo Date: Wed, 20 Apr 2022 20:19:27 +0900 Subject: [PATCH 3/7] render markdownEditorInput when isEditing is true --- .../__snapshots__/cardDialog.test.tsx.snap | 360 ---------- .../__snapshots__/centerPanel.test.tsx.snap | 658 ------------------ .../__snapshots__/contentBlock.test.tsx.snap | 47 -- .../markdownEditor.test.tsx.snap | 142 +--- .../__snapshots__/viewTitle.test.tsx.snap | 141 ---- .../__snapshots__/workspace.test.tsx.snap | 188 ----- .../cardDetailContents.test.tsx.snap | 45 -- .../__snapshots__/textElement.test.tsx.snap | 45 -- webapp/src/components/markdownEditor.tsx | 3 +- .../markdownEditorInput.scss | 4 - .../markdownEditorInput.tsx | 7 +- 11 files changed, 4 insertions(+), 1636 deletions(-) diff --git a/webapp/src/components/__snapshots__/cardDialog.test.tsx.snap b/webapp/src/components/__snapshots__/cardDialog.test.tsx.snap index 5efc9f143..9195867f6 100644 --- a/webapp/src/components/__snapshots__/cardDialog.test.tsx.snap +++ b/webapp/src/components/__snapshots__/cardDialog.test.tsx.snap @@ -132,51 +132,6 @@ exports[`components/cardDialog already following card 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -204,51 +159,6 @@ exports[`components/cardDialog already following card 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -622,51 +532,6 @@ exports[`components/cardDialog return cardDialog menu content 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -694,51 +559,6 @@ exports[`components/cardDialog return cardDialog menu content 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -898,51 +718,6 @@ exports[`components/cardDialog return cardDialog menu content and cancel delete class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -970,51 +745,6 @@ exports[`components/cardDialog return cardDialog menu content and cancel delete class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1174,51 +904,6 @@ exports[`components/cardDialog should match snapshot 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1246,51 +931,6 @@ exports[`components/cardDialog should match snapshot 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
diff --git a/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap b/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap index e1fb4b226..59c34f00f 100644 --- a/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap +++ b/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap @@ -87,53 +87,6 @@ exports[`components/centerPanel return centerPanel and click on card to show car class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -643,53 +596,6 @@ exports[`components/centerPanel return centerPanel and press touch 1 with readon class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1118,53 +1024,6 @@ exports[`components/centerPanel return centerPanel and press touch ctrl+d for on class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1749,53 +1608,6 @@ exports[`components/centerPanel return centerPanel and press touch del for one c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -2380,53 +2192,6 @@ exports[`components/centerPanel return centerPanel and press touch esc for one c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -3011,53 +2776,6 @@ exports[`components/centerPanel return centerPanel and press touch esc for one c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -3642,53 +3360,6 @@ exports[`components/centerPanel return centerPanel and press touch esc for two c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -4273,53 +3944,6 @@ exports[`components/centerPanel return centerPanel and press touch esc for two c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -4904,53 +4528,6 @@ exports[`components/centerPanel return centerPanel and press touch esc for two c class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -5535,53 +5112,6 @@ exports[`components/centerPanel return centerPanel and select one card and click class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -6166,53 +5696,6 @@ exports[`components/centerPanel return centerPanel and select one card and click class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -6797,53 +6280,6 @@ exports[`components/centerPanel should match snapshot for Gallery 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -7106,53 +6542,6 @@ exports[`components/centerPanel should match snapshot for Kanban 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -8137,53 +7526,6 @@ exports[`components/centerPanel should match snapshot for Table 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
diff --git a/webapp/src/components/__snapshots__/contentBlock.test.tsx.snap b/webapp/src/components/__snapshots__/contentBlock.test.tsx.snap index 82b385b0e..468225c5f 100644 --- a/webapp/src/components/__snapshots__/contentBlock.test.tsx.snap +++ b/webapp/src/components/__snapshots__/contentBlock.test.tsx.snap @@ -456,53 +456,6 @@ exports[`components/contentBlock should match snapshot with textBlock 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
-
-
-
- -
-
-
`; @@ -67,53 +22,6 @@ exports[`components/markdownEditor should match snapshot with initial text 1`] = class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
`; @@ -122,55 +30,7 @@ exports[`components/markdownEditor should match snapshot with on click on previe
-
-
-
- -
-
-
-
+ />
`; diff --git a/webapp/src/components/__snapshots__/viewTitle.test.tsx.snap b/webapp/src/components/__snapshots__/viewTitle.test.tsx.snap index 02e3af01f..d13f025d6 100644 --- a/webapp/src/components/__snapshots__/viewTitle.test.tsx.snap +++ b/webapp/src/components/__snapshots__/viewTitle.test.tsx.snap @@ -152,53 +152,6 @@ exports[`components/viewTitle should match snapshot 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -246,53 +199,6 @@ exports[`components/viewTitle should match snapshot readonly 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -356,53 +262,6 @@ exports[`components/viewTitle show description 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
diff --git a/webapp/src/components/__snapshots__/workspace.test.tsx.snap b/webapp/src/components/__snapshots__/workspace.test.tsx.snap index 015c64e93..767f23f92 100644 --- a/webapp/src/components/__snapshots__/workspace.test.tsx.snap +++ b/webapp/src/components/__snapshots__/workspace.test.tsx.snap @@ -354,53 +354,6 @@ exports[`src/components/workspace return workspace and showcard 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -918,53 +871,6 @@ exports[`src/components/workspace return workspace readonly and showcard 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1571,53 +1477,6 @@ exports[`src/components/workspace should match snapshot 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -2135,53 +1994,6 @@ exports[`src/components/workspace should match snapshot with readonly 1`] = ` class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
diff --git a/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap b/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap index a91ee675c..feb26362a 100644 --- a/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap +++ b/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap @@ -22,51 +22,6 @@ exports[`components/cardDetail/cardDetailContents should match snapshot 1`] = ` Add a description...

-
-
-
- -
-
-
diff --git a/webapp/src/components/content/__snapshots__/textElement.test.tsx.snap b/webapp/src/components/content/__snapshots__/textElement.test.tsx.snap index 203758646..a1df4675d 100644 --- a/webapp/src/components/content/__snapshots__/textElement.test.tsx.snap +++ b/webapp/src/components/content/__snapshots__/textElement.test.tsx.snap @@ -9,51 +9,6 @@ exports[`components/content/TextElement return a textElement 1`] = ` class="octo-editor-preview octo-placeholder" data-testid="preview-element" /> -
-
-
- -
-
-
`; diff --git a/webapp/src/components/markdownEditor.tsx b/webapp/src/components/markdownEditor.tsx index 2359d93f4..8f3f6dc1b 100644 --- a/webapp/src/components/markdownEditor.tsx +++ b/webapp/src/components/markdownEditor.tsx @@ -64,8 +64,7 @@ const MarkdownEditor = (props: Props): JSX.Element => { const element = (
- {!isEditing && previewElement} - {editorElement} + {isEditing ? editorElement : previewElement}
) diff --git a/webapp/src/components/markdownEditorInput/markdownEditorInput.scss b/webapp/src/components/markdownEditorInput/markdownEditorInput.scss index de4635b10..83e1388ae 100644 --- a/webapp/src/components/markdownEditorInput/markdownEditorInput.scss +++ b/webapp/src/components/markdownEditorInput/markdownEditorInput.scss @@ -4,10 +4,6 @@ align-items: center; } - &--IsNotEditing { - display: none; - } - span[data-testid='mentionText'] { background: rgba(var(--button-bg-rgb), 0.16); border-radius: 4px; diff --git a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx index f687e01e5..fdd2a296d 100644 --- a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx +++ b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx @@ -36,7 +36,7 @@ type Props = { } const MarkdownEditorInput = (props: Props): ReactElement => { - const {onChange, onFocus, onBlur, initialText, id, isEditing} = props + const {onChange, onFocus, onBlur, initialText, id} = props const boardUsers = useAppSelector(getBoardUsersList) const mentions: MentionData[] = useMemo(() => boardUsers.map((user) => ({name: user.username, avatar: `${imageURLForUser ? imageURLForUser(user.id) : ''}`, is_bot: user.is_bot})), [boardUsers]) const ref = useRef(null) @@ -142,10 +142,7 @@ const MarkdownEditorInput = (props: Props): ReactElement => { setSuggestions(defaultSuggestionsFilter(value, mentions)) }, [mentions]) - let className = 'MarkdownEditorInput' - if (!isEditing) { - className += ' MarkdownEditorInput--IsNotEditing' - } + const className = 'MarkdownEditorInput' return (
Date: Wed, 20 Apr 2022 21:21:36 +0900 Subject: [PATCH 4/7] fix cypress test --- webapp/cypress/integration/createBoard.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/webapp/cypress/integration/createBoard.ts b/webapp/cypress/integration/createBoard.ts index 512ed5c62..431420fe8 100644 --- a/webapp/cypress/integration/createBoard.ts +++ b/webapp/cypress/integration/createBoard.ts @@ -194,10 +194,13 @@ describe('Create and delete board / card', () => { cy.get('.ViewHeader').contains('New').click() cy.get('.CardDetail').should('exist') - cy.log('**Add comment**') - cy.get('.CommentsList').findAllByTestId('preview-element').click() + cy.wait(1000) - cy.get('.MarkdownEditorInput').should('exist'). + cy.log('**Add comment**') + cy.get('.CommentsList'). + findAllByTestId('preview-element'). + click(). + get('.CommentsList .MarkdownEditorInput'). type('Test Text') cy.log('**Cut comment**') From 3ada15a6e8622bee723b5cd3e61a23e64262416a Mon Sep 17 00:00:00 2001 From: kyeongsoosoo Date: Wed, 20 Apr 2022 21:48:16 +0900 Subject: [PATCH 5/7] fix cypress test --- webapp/cypress/integration/createBoard.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/webapp/cypress/integration/createBoard.ts b/webapp/cypress/integration/createBoard.ts index 431420fe8..81db65ea2 100644 --- a/webapp/cypress/integration/createBoard.ts +++ b/webapp/cypress/integration/createBoard.ts @@ -185,6 +185,8 @@ describe('Create and delete board / card', () => { }) it('GH-2520 make cut/undo/redo work in comments', () => { + const isMAC = navigator.userAgent.indexOf("Mac") !== -1 + const ctrlKey = isMAC ? 'meta' : 'ctrl' // Visit a page and create new empty board cy.visit('/') cy.uiCreateEmptyBoard() @@ -211,12 +213,12 @@ describe('Create and delete board / card', () => { cy.log('**Undo comment**') cy.get('.CommentsList .MarkdownEditorInput'). - type('{meta+z}'). + type(`{${ctrlKey}+z}`). should('have.text', 'Test Text') cy.log('**Redo comment**') cy.get('.CommentsList .MarkdownEditorInput'). - type('{shift+meta+z}'). + type(`{shift+${ctrlKey}+z}`). should('have.text', '') }) }) From 0d9c3da1c8effe08490a882b88e0398683698eb8 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Tue, 23 Aug 2022 10:43:25 -0600 Subject: [PATCH 6/7] Update webapp/src/components/markdownEditorInput/markdownEditorInput.tsx --- .../src/components/markdownEditorInput/markdownEditorInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx index bd388af4f..8e6a96177 100644 --- a/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx +++ b/webapp/src/components/markdownEditorInput/markdownEditorInput.tsx @@ -7,7 +7,7 @@ import createMentionPlugin from '@draft-js-plugins/mention' import '@draft-js-plugins/mention/lib/plugin.css' import {ContentState, DraftHandleValue, EditorState, getDefaultKeyBinding} from 'draft-js' import React, { - ReactElement, useCallback, + ReactElement, useCallback, useEffect, useMemo, useRef, useState, } from 'react' From aa0ed504d04e1810b018c5670f87da6e7518e326 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 25 Aug 2022 08:53:40 -0600 Subject: [PATCH 7/7] update unit tests --- .../__snapshots__/centerPanel.test.tsx.snap | 94 ------------------- 1 file changed, 94 deletions(-) diff --git a/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap b/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap index e5cd9b5c0..2bf355666 100644 --- a/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap +++ b/webapp/src/components/__snapshots__/centerPanel.test.tsx.snap @@ -786,53 +786,6 @@ exports[`components/centerPanel return centerPanel and click on card to show car class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-
@@ -1386,53 +1339,6 @@ exports[`components/centerPanel return centerPanel and click on new card to edit class="octo-editor-preview" data-testid="preview-element" /> -
-
-
- -
-
-