diff --git a/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap b/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap
new file mode 100644
index 000000000..f142263c9
--- /dev/null
+++ b/webapp/src/components/cardDetail/__snapshots__/cardDetailContents.test.tsx.snap
@@ -0,0 +1,979 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`components/cardDetail/cardDetailContents should match snapshot 1`] = `
+
+
+
+
+
+
+
+ Add a description...
+
+
+
+
+
+
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot after drag and drop event 1`] = `
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot after drag and drop event 2 1`] = `
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot after drag and drop event 3 1`] = `
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot after onBlur triggers 1`] = `
+
+
+
+
+
+
+
+ Add a description...
+
+
+
+
+
+
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot with contents array 1`] = `
+
+`;
+
+exports[`components/cardDetail/cardDetailContents should match snapshot with contents array that has array inside it 1`] = `
+
+`;
diff --git a/webapp/src/components/cardDetail/cardDetailContents.test.tsx b/webapp/src/components/cardDetail/cardDetailContents.test.tsx
new file mode 100644
index 000000000..0de7fa276
--- /dev/null
+++ b/webapp/src/components/cardDetail/cardDetailContents.test.tsx
@@ -0,0 +1,248 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+import React from 'react'
+
+import {fireEvent, render} from '@testing-library/react'
+
+import {IntlProvider} from 'react-intl'
+import {act} from 'react-dom/test-utils'
+
+import {DndProvider} from 'react-dnd'
+import {HTML5Backend} from 'react-dnd-html5-backend'
+
+import {TestBlockFactory} from '../../test/testBlockFactory'
+
+import {mockDOM} from '../../testUtils'
+
+import CardDetailContents from './cardDetailContents'
+
+const wrapProviders = (children: any) => {
+ return (
+
+ {children}
+
+ )
+}
+
+global.fetch = jest.fn()
+
+beforeAll(() => {
+ mockDOM()
+})
+
+describe('components/cardDetail/cardDetailContents', () => {
+ const board = TestBlockFactory.createBoard()
+ board.fields.cardProperties = [
+ {
+ id: 'property_id_1',
+ name: 'Owner',
+ type: 'select',
+ options: [
+ {
+ color: 'propColorDefault',
+ id: 'property_value_id_1',
+ value: 'Jean-Luc Picard',
+ },
+ {
+ color: 'propColorDefault',
+ id: 'property_value_id_2',
+ value: 'William Riker',
+ },
+ {
+ color: 'propColorDefault',
+ id: 'property_value_id_3',
+ value: 'Deanna Troi',
+ },
+ ],
+ },
+ ]
+
+ const card = TestBlockFactory.createCard(board)
+
+ test('should match snapshot', async () => {
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot with contents array', async () => {
+ const contents = [TestBlockFactory.createDivider(card)]
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot after onBlur triggers', async () => {
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+ const markdownEditorField = container!.querySelector('.octo-editor-preview.octo-placeholder')
+ expect(markdownEditorField).toBeDefined()
+ fireEvent.click(markdownEditorField!)
+
+ const onFocusEvent = new FocusEvent('focus', {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ })
+
+ const onBlurEvent = new FocusEvent('blur', {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ })
+
+ const textareaContainer = container!.querySelectorAll('.CodeMirror.cm-s-easymde.CodeMirror-wrap')
+ const textarea = textareaContainer[textareaContainer.length - 1].querySelector('textarea')
+
+ await act(async () => {
+ textarea!.dispatchEvent(onFocusEvent)
+ fireEvent.input(textarea!, {target: {value: 'test123'}})
+ fireEvent.keyPress(textarea!, {key: 'Escape', code: 'Escape'})
+ textarea!.dispatchEvent(onBlurEvent)
+ })
+
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot with contents array that has array inside it', async () => {
+ const contents = [TestBlockFactory.createDivider(card), [TestBlockFactory.createDivider(card), TestBlockFactory.createDivider(card)]]
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot after drag and drop event', async () => {
+ const contents = [TestBlockFactory.createDivider(card), [TestBlockFactory.createDivider(card), TestBlockFactory.createDivider(card)]]
+ card.fields.contentOrder = contents.map((content) => (Array.isArray(content) ? content.map((c) => c.id) : (content as any).id))
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+
+ const drag = container!.querySelectorAll('.dnd-handle')[0]
+ const drop = container!.querySelectorAll('.addToRow')[4]
+
+ fireEvent.dragStart(drag)
+ fireEvent.dragEnter(drop)
+ fireEvent.dragOver(drop)
+ fireEvent.drop(drop)
+
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot after drag and drop event 2', async () => {
+ const contents = [TestBlockFactory.createDivider(card), TestBlockFactory.createDivider(card)]
+ card.fields.contentOrder = contents.map((content) => (Array.isArray(content) ? content.map((c) => c.id) : (content as any).id))
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+
+ const drag = container!.querySelectorAll('.dnd-handle')[0]
+ const drop = container!.querySelectorAll('.addToRow')[4]
+
+ fireEvent.dragStart(drag)
+ fireEvent.dragEnter(drop)
+ fireEvent.dragOver(drop)
+ fireEvent.drop(drop)
+
+ expect(container).toMatchSnapshot()
+ })
+
+ test('should match snapshot after drag and drop event 3', async () => {
+ const contents = [TestBlockFactory.createDivider(card), TestBlockFactory.createDivider(card)]
+ card.fields.contentOrder = contents.map((content) => (Array.isArray(content) ? content.map((c) => c.id) : (content as any).id))
+ const component = wrapProviders((
+
+ ))
+
+ let container: Element | undefined
+ await act(async () => {
+ const result = render(component)
+ container = result.container
+ })
+
+ const drag = container!.querySelectorAll('.dnd-handle')[1]
+ const drop = container!.querySelectorAll('.addToRow')[2]
+
+ fireEvent.dragStart(drag)
+ fireEvent.dragEnter(drop)
+ fireEvent.dragOver(drop)
+ fireEvent.drop(drop)
+
+ expect(container).toMatchSnapshot()
+ })
+})
diff --git a/webapp/src/components/cardDetail/cardDetailContents.tsx b/webapp/src/components/cardDetail/cardDetailContents.tsx
index 8e9593c9e..f37791462 100644
--- a/webapp/src/components/cardDetail/cardDetailContents.tsx
+++ b/webapp/src/components/cardDetail/cardDetailContents.tsx
@@ -12,9 +12,12 @@ import {useSortableWithGrip} from '../../hooks/sortable'
import ContentBlock from '../contentBlock'
import {MarkdownEditor} from '../markdownEditor'
+import {dragAndDropRearrange} from './cardDetailContentsUtility'
+
export type Position = 'left' | 'right' | 'above' | 'below' | 'aboveRow' | 'belowRow'
type Props = {
+ id?: string
card: Card
contents: Array
readonly: boolean
@@ -51,59 +54,20 @@ function moveBlock(card: Card, srcBlock: IContentBlockWithCords, dstBlock: ICont
const dstBlockId = dstBlock.block.id
const srcBlockX = srcBlock.cords.x
- let dstBlockX = dstBlock.cords.x
+ const dstBlockX = dstBlock.cords.x
const srcBlockY = (srcBlock.cords.y || srcBlock.cords.y === 0) && (srcBlock.cords.y > -1) ? srcBlock.cords.y : -1
- let dstBlockY = (dstBlock.cords.y || dstBlock.cords.y === 0) && (dstBlock.cords.y > -1) ? dstBlock.cords.y : -1
+ const dstBlockY = (dstBlock.cords.y || dstBlock.cords.y === 0) && (dstBlock.cords.y > -1) ? dstBlock.cords.y : -1
if (srcBlockId === dstBlockId) {
return
}
- // Delete Src Block
- if (srcBlockY > -1) {
- (contentOrder[srcBlockX] as string[]).splice(srcBlockY, 1)
-
- if (contentOrder[srcBlockX].length === 1 && srcBlockX !== dstBlockX) {
- contentOrder.splice(srcBlockX, 1, contentOrder[srcBlockX][0])
- }
- } else {
- contentOrder.splice(srcBlockX, 1)
-
- if (dstBlockX > srcBlockX) {
- dstBlockX -= 1
- }
- }
-
- if (moveTo === 'right') {
- if (dstBlockY > -1) {
- if (dstBlockX === srcBlockX && dstBlockY > srcBlockY) {
- dstBlockY -= 1
- }
-
- (contentOrder[dstBlockX] as string[]).splice(dstBlockY + 1, 0, srcBlockId)
- } else {
- contentOrder.splice(dstBlockX, 1, [dstBlockId, srcBlockId])
- }
- } else if (moveTo === 'left') {
- if (dstBlockY > -1) {
- if (dstBlockX === srcBlockX && dstBlockY > srcBlockY) {
- dstBlockY -= 1
- }
-
- (contentOrder[dstBlockX] as string[]).splice(dstBlockY, 0, srcBlockId)
- } else {
- contentOrder.splice(dstBlockX, 1, [srcBlockId, dstBlockId])
- }
- } else if (moveTo === 'aboveRow') {
- contentOrder.splice(dstBlockX, 0, srcBlockId)
- } else if (moveTo === 'belowRow') {
- contentOrder.splice(dstBlockX + 1, 0, srcBlockId)
- }
+ const newContentOrder = dragAndDropRearrange({contentOrder, srcBlockId, srcBlockX, srcBlockY, dstBlockId, dstBlockX, dstBlockY, moveTo})
mutator.performAsUndoGroup(async () => {
const description = intl.formatMessage({id: 'CardDetail.moveContent', defaultMessage: 'move card content'})
- await mutator.changeCardContentOrder(card, contentOrder, description)
+ await mutator.changeCardContentOrder(card, newContentOrder, description)
})
}
@@ -185,11 +149,8 @@ const ContentBlockWithDragAndDrop = (props: ContentBlockWithDragAndDropProps) =>
const CardDetailContents = React.memo((props: Props) => {
const intl = useIntl()
- const {contents, card} = props
- if (!contents) {
- return null
- }
- if (contents.length > 0) {
+ const {contents, card, id} = props
+ if (contents.length) {
return (
{contents.map((block, x) =>
@@ -214,6 +175,7 @@ const CardDetailContents = React.memo((props: Props) => {
{!props.readonly &&
{
diff --git a/webapp/src/components/cardDetail/cardDetailContentsUtility.test.ts b/webapp/src/components/cardDetail/cardDetailContentsUtility.test.ts
new file mode 100644
index 000000000..7e427ba73
--- /dev/null
+++ b/webapp/src/components/cardDetail/cardDetailContentsUtility.test.ts
@@ -0,0 +1,271 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {dragAndDropRearrange} from './cardDetailContentsUtility'
+import {Position} from './cardDetailContents'
+
+describe('components/cardDetail/cardDetailContentsUtility', () => {
+ test('Testing moving first item in the row to the end', () => {
+ const data = {
+ contentOrder: [
+ ['1', '2', '3'],
+ ],
+ srcBlockId: '1',
+ srcBlockX: 0,
+ srcBlockY: 0,
+ dstBlockX: 0,
+ dstBlockY: 2,
+ dstBlockId: '3',
+ moveTo: 'right' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['2', '3', '1'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving last item in the row to the beginning', () => {
+ const data = {
+ contentOrder: [
+ ['1', '2', '3'],
+ ],
+ srcBlockId: '3',
+ srcBlockX: 0,
+ srcBlockY: 2,
+ dstBlockX: 0,
+ dstBlockY: 0,
+ dstBlockId: '1',
+ moveTo: 'left' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['3', '1', '2'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving item from beginning of row to the middle of row', () => {
+ const data = {
+ contentOrder: [
+ ['1', '2', '3'],
+ ],
+ srcBlockId: '1',
+ srcBlockX: 0,
+ srcBlockY: 0,
+ dstBlockX: 0,
+ dstBlockY: 2,
+ dstBlockId: '3',
+ moveTo: 'left' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['2', '1', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing swapping two items in the same row by moving second item to the left of the first item', () => {
+ const data = {
+ contentOrder: [
+ ['1', '2'],
+ ],
+ srcBlockId: '2',
+ srcBlockX: 0,
+ srcBlockY: 1,
+ dstBlockX: 0,
+ dstBlockY: 0,
+ dstBlockId: '1',
+ moveTo: 'left' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['2', '1'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing swapping two items in the same row by moving the first item to the right of the second item', () => {
+ const data = {
+ contentOrder: [
+ ['1', '2'],
+ ],
+ srcBlockId: '1',
+ srcBlockX: 0,
+ srcBlockY: 0,
+ dstBlockX: 0,
+ dstBlockY: 1,
+ dstBlockId: '2',
+ moveTo: 'right' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['2', '1'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving a single item in the first row into the middle of second row using left operation', () => {
+ const data = {
+ contentOrder: [
+ '4',
+ ['1', '3'],
+ ],
+ srcBlockId: '4',
+ srcBlockX: 0,
+ srcBlockY: -1,
+ dstBlockX: 1,
+ dstBlockY: 1,
+ dstBlockId: '3',
+ moveTo: 'left' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['1', '4', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving a single item in the first row into the middle of second row using right operation', () => {
+ const data = {
+ contentOrder: [
+ '4',
+ ['1', '3'],
+ ],
+ srcBlockId: '4',
+ srcBlockX: 0,
+ srcBlockY: -1,
+ dstBlockX: 1,
+ dstBlockY: 0,
+ dstBlockId: '1',
+ moveTo: 'right' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['1', '4', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving a single item in the last row into the middle of first row', () => {
+ const data = {
+ contentOrder: [
+ ['1', '3'],
+ '4',
+ ],
+ srcBlockId: '4',
+ srcBlockX: 1,
+ srcBlockY: -1,
+ dstBlockX: 0,
+ dstBlockY: 0,
+ dstBlockId: '1',
+ moveTo: 'right' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ ['1', '4', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving a single item in the last row above the first row', () => {
+ const data = {
+ contentOrder: [
+ ['1', '3'],
+ '4',
+ ],
+ srcBlockId: '4',
+ srcBlockX: 1,
+ srcBlockY: -1,
+ dstBlockX: 0,
+ dstBlockY: 0,
+ dstBlockId: '1',
+ moveTo: 'aboveRow' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ '4',
+ ['1', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving an item out of a row', () => {
+ const data = {
+ contentOrder: [
+ ['1', '3'],
+ '4',
+ ],
+ srcBlockId: '3',
+ srcBlockX: 0,
+ srcBlockY: 1,
+ dstBlockX: 1,
+ dstBlockY: -1,
+ dstBlockId: '4',
+ moveTo: 'belowRow' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ '1',
+ '4',
+ '3',
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving an item out of a row and creating a new row with a single item at the end', () => {
+ const data = {
+ contentOrder: [
+ ['1', '3'],
+ '4',
+ ],
+ srcBlockId: '3',
+ srcBlockX: 0,
+ srcBlockY: 1,
+ dstBlockX: 1,
+ dstBlockY: -1,
+ dstBlockId: '4',
+ moveTo: 'right' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ '1',
+ ['4', '3'],
+ ]
+ expect(result).toEqual(expected)
+ })
+
+ test('Testing moving an item out of a row and creating a new row with a single item at the beginning', () => {
+ const data = {
+ contentOrder: [
+ ['1', '3'],
+ '4',
+ ],
+ srcBlockId: '3',
+ srcBlockX: 0,
+ srcBlockY: 1,
+ dstBlockX: 1,
+ dstBlockY: -1,
+ dstBlockId: '4',
+ moveTo: 'left' as Position,
+ }
+
+ const result = dragAndDropRearrange(data)
+ const expected = [
+ '1',
+ ['3', '4'],
+ ]
+ expect(result).toEqual(expected)
+ })
+})
diff --git a/webapp/src/components/cardDetail/cardDetailContentsUtility.ts b/webapp/src/components/cardDetail/cardDetailContentsUtility.ts
new file mode 100644
index 000000000..29b5c9899
--- /dev/null
+++ b/webapp/src/components/cardDetail/cardDetailContentsUtility.ts
@@ -0,0 +1,71 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+import {Position} from './cardDetailContents'
+
+type DragAndDropRearrangeData = {
+ contentOrder: Array,
+ srcBlockId: string,
+ srcBlockX: number,
+ srcBlockY: number,
+ dstBlockX: number,
+ dstBlockY: number,
+ dstBlockId: string,
+ moveTo: Position,
+}
+
+export const dragAndDropRearrange =
+ (data: DragAndDropRearrangeData): Array => {
+ const {contentOrder, srcBlockX, srcBlockY, dstBlockX, dstBlockY, moveTo, srcBlockId, dstBlockId} = data
+ const newContentOrder: Array = JSON.parse(JSON.stringify(contentOrder))
+
+ const copySrcBlockX = srcBlockX
+ const copySrcBlockY = srcBlockY
+
+ let copyDstBlockX = dstBlockX
+ let copyDstBlockY = dstBlockY
+
+ // Delete the block we are moving first then move it to the correct place
+
+ // Delete Src Block
+ if (copySrcBlockY > -1) {
+ (newContentOrder[copySrcBlockX] as string[]).splice(copySrcBlockY, 1)
+
+ if (newContentOrder[copySrcBlockX].length === 1 && copySrcBlockX !== copyDstBlockX) {
+ newContentOrder.splice(copySrcBlockX, 1, newContentOrder[copySrcBlockX][0])
+ }
+ } else {
+ newContentOrder.splice(copySrcBlockX, 1)
+
+ if (copyDstBlockX > copySrcBlockX) {
+ copyDstBlockX -= 1
+ }
+ }
+
+ if (moveTo === 'right') {
+ if (copyDstBlockY > -1) {
+ if (copyDstBlockX === copySrcBlockX && copyDstBlockY > copySrcBlockY && copySrcBlockY > -1) {
+ copyDstBlockY -= 1
+ }
+
+ (newContentOrder[copyDstBlockX] as string[]).splice(copyDstBlockY + 1, 0, srcBlockId)
+ } else {
+ newContentOrder.splice(copyDstBlockX, 1, [dstBlockId, srcBlockId])
+ }
+ } else if (moveTo === 'left') {
+ if (copyDstBlockY > -1) {
+ if (copyDstBlockX === copySrcBlockX && copyDstBlockY > copySrcBlockY && copySrcBlockY > -1) {
+ copyDstBlockY -= 1
+ }
+
+ (newContentOrder[copyDstBlockX] as string[]).splice(copyDstBlockY, 0, srcBlockId)
+ } else {
+ newContentOrder.splice(copyDstBlockX, 1, [srcBlockId, dstBlockId])
+ }
+ } else if (moveTo === 'aboveRow') {
+ newContentOrder.splice(copyDstBlockX, 0, srcBlockId)
+ } else if (moveTo === 'belowRow') {
+ newContentOrder.splice(copyDstBlockX + 1, 0, srcBlockId)
+ }
+
+ return newContentOrder
+ }
diff --git a/webapp/src/components/cardDetail/cardDetailProperties.test.tsx b/webapp/src/components/cardDetail/cardDetailProperties.test.tsx
index 61d4f90c1..abbc76071 100644
--- a/webapp/src/components/cardDetail/cardDetailProperties.test.tsx
+++ b/webapp/src/components/cardDetail/cardDetailProperties.test.tsx
@@ -60,7 +60,7 @@ describe('components/cardDetail/CardDetailProperties', () => {
cardTemplate.fields.isTemplate = true
test('should match snapshot', async () => {
- const componet = wrapIntl((
+ const component = wrapIntl((
{
/>
))
- const {container} = render(componet)
+ const {container} = render(component)
expect(container).toMatchSnapshot()
})
diff --git a/webapp/src/components/contentBlock.tsx b/webapp/src/components/contentBlock.tsx
index 73fb9a0e3..f933a2c6a 100644
--- a/webapp/src/components/contentBlock.tsx
+++ b/webapp/src/components/contentBlock.tsx
@@ -43,7 +43,16 @@ const ContentBlock = React.memo((props: Props): JSX.Element => {
const index = cords.x
const colIndex = (cords.y || cords.y === 0) && cords.y > -1 ? cords.y : -1
- const contentOrder = card.fields.contentOrder.slice()
+ const contentOrder: Array = []
+ if (card.fields.contentOrder) {
+ for (const contentId of card.fields.contentOrder) {
+ if (typeof contentId === 'string') {
+ contentOrder.push(contentId)
+ } else {
+ contentOrder.push(contentId.slice())
+ }
+ }
+ }
const className = 'ContentBlock octo-block'
return (
diff --git a/webapp/src/components/markdownEditor.tsx b/webapp/src/components/markdownEditor.tsx
index 062bd0ef3..b7387f600 100644
--- a/webapp/src/components/markdownEditor.tsx
+++ b/webapp/src/components/markdownEditor.tsx
@@ -7,6 +7,7 @@ import {Utils} from '../utils'
import './markdownEditor.scss'
type Props = {
+ id?: string
text?: string
placeholderText?: string
className?: string
@@ -19,10 +20,10 @@ type Props = {
}
const MarkdownEditor = (props: Props): JSX. Element => {
- const {placeholderText, onFocus, onBlur, onChange, text} = props
- const [uniqueId] = useState(Utils.createGuid())
-
+ const {placeholderText, onFocus, onBlur, onChange, text, id} = props
const [isEditing, setIsEditing] = useState(false)
+ const [uniqueId] = useState(id || Utils.createGuid())
+
const [active, setActive] = useState(false)
const [editorInstance, setEditorInstance] = useState()
const editorOptions = useMemo(() => ({