Skip to content

Commit 8bf95c5

Browse files
authored
RI-6954: Edit ReJSONs with Monaco editor (#286)
1 parent 7881fe4 commit 8bf95c5

5 files changed

Lines changed: 75 additions & 50 deletions

File tree

src/webviews/src/modules/key-details/components/rejson-details/components/edit-entire-item-action/EditEntireItemAction.spec.tsx

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,51 @@ import { EditEntireItemAction, Props } from './EditEntireItemAction'
55
import { JSONErrors } from '../../constants'
66

77
const mockedProps = mock<Props>()
8-
98
const valueOfEntireItem = '"Sample string"'
109

1110
describe('EditEntireItemAction', () => {
1211
it('renders correctly with provided props', () => {
13-
render(<EditEntireItemAction
14-
{...instance(mockedProps)}
15-
initialValue={valueOfEntireItem}
16-
/>)
12+
render(
13+
<EditEntireItemAction
14+
{...instance(mockedProps)}
15+
initialValue={valueOfEntireItem}
16+
/>,
17+
)
1718

1819
expect(screen.getByTestId('json-value')).toBeInTheDocument()
1920
expect(screen.getByTestId('json-value')).toHaveValue(valueOfEntireItem)
2021
})
2122

2223
it('triggers handleUpdateValueFormSubmit when the form is submitted', () => {
2324
const handleUpdateValueFormSubmit = vi.fn()
24-
render(<EditEntireItemAction
25-
{...instance(mockedProps)}
26-
initialValue={valueOfEntireItem}
27-
onSubmit={handleUpdateValueFormSubmit}
28-
/>)
25+
26+
render(
27+
<EditEntireItemAction
28+
{...instance(mockedProps)}
29+
initialValue={valueOfEntireItem}
30+
onSubmit={handleUpdateValueFormSubmit}
31+
/>,
32+
)
2933

3034
fireEvent.submit(screen.getByTestId('json-entire-form'))
3135
expect(handleUpdateValueFormSubmit).toHaveBeenCalled()
3236
})
3337

34-
it('shouuld show error and do not submit', () => {
38+
it('should show error and not submit', () => {
3539
const handleUpdateValueFormSubmit = vi.fn()
36-
render(<EditEntireItemAction
37-
{...instance(mockedProps)}
38-
initialValue="xxxx"
39-
onSubmit={handleUpdateValueFormSubmit}
40-
/>)
40+
41+
render(
42+
<EditEntireItemAction
43+
{...instance(mockedProps)}
44+
initialValue="xxxx"
45+
onSubmit={handleUpdateValueFormSubmit}
46+
/>,
47+
)
4148

4249
fireEvent.submit(screen.getByTestId('json-entire-form'))
43-
expect(screen.getByTestId('edit-json-error')).toHaveTextContent(JSONErrors.valueJSONFormat)
50+
expect(screen.getByTestId('edit-json-error')).toHaveTextContent(
51+
JSONErrors.valueJSONFormat,
52+
)
4453
expect(handleUpdateValueFormSubmit).not.toHaveBeenCalled()
4554
})
4655
})

src/webviews/src/modules/key-details/components/rejson-details/components/edit-entire-item-action/EditEntireItemAction.tsx

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import React, { ChangeEvent, useRef, useState } from 'react'
1+
import React, { useRef, useState } from 'react'
22
import cx from 'classnames'
33
import { VSCodeButton } from '@vscode/webview-ui-toolkit/react'
44
import { VscCheck, VscChromeClose } from 'react-icons/vsc'
55
import useOnclickOutside from 'react-cool-onclickoutside'
66
import { GoAlert } from 'react-icons/go'
7-
import * as l10n from '@vscode/l10n'
87

98
import { FieldMessage } from 'uiSrc/components'
109
import { Nullable } from 'uiSrc/interfaces'
1110
import { Keys } from 'uiSrc/constants'
12-
import { TextArea } from 'uiSrc/ui'
1311

12+
import { MonacoJson } from 'uiSrc/components/monaco-editor'
1413
import { isValidJSON } from '../../utils'
1514
import { JSONErrors } from '../../constants'
1615

@@ -23,15 +22,13 @@ export interface Props {
2322
}
2423

2524
export const EditEntireItemAction = (props: Props) => {
26-
const {
27-
initialValue,
28-
onCancel,
29-
onSubmit,
30-
} = props
25+
const { initialValue, onCancel, onSubmit } = props
3126
const [value, setValue] = useState<string>(initialValue)
3227
const [error, setError] = useState<Nullable<string>>(null)
3328

34-
const handleClickOutside = () => { onCancel?.() }
29+
const handleClickOutside = () => {
30+
onCancel?.()
31+
}
3532

3633
const textareaRef = useRef<HTMLTextAreaElement>(null)
3734

@@ -66,16 +63,14 @@ export const EditEntireItemAction = (props: Props) => {
6663
onKeyDown={handleKeyDown}
6764
>
6865
<div className="grow">
69-
<TextArea
70-
autoFocus
71-
inputRef={textareaRef}
72-
invalid={!!error}
73-
className={styles.fullWidthTextArea}
74-
value={value}
75-
placeholder={l10n.t('Enter JSON value')}
76-
onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)}
77-
data-testid="json-value"
78-
/>
66+
<div className={styles.editor}>
67+
<MonacoJson
68+
wrapperClassName={styles.editorWrapper}
69+
value={value}
70+
onChange={setValue}
71+
data-testid="json-value"
72+
/>
73+
</div>
7974
</div>
8075
<div className={cx(styles.controls, styles.controlsBottom)}>
8176
<VSCodeButton
@@ -100,7 +95,9 @@ export const EditEntireItemAction = (props: Props) => {
10095
</div>
10196
</form>
10297
{error && (
103-
<div className={cx(styles.errorMessage, styles.errorMessageForTextArea)}>
98+
<div
99+
className={cx(styles.errorMessage, styles.errorMessageForTextArea)}
100+
>
104101
<FieldMessage
105102
scrollViewOnAppear
106103
Icon={<GoAlert />}

src/webviews/src/modules/key-details/components/rejson-details/styles.module.scss

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@
4444
}
4545

4646
.row {
47-
@apply min-h-[25px] relative flex items-end;
47+
@apply relative flex items-end;
4848

4949
&:last-child {
5050
@apply pb-3;
5151
}
5252

5353
&:before {
5454
@apply block absolute h-full top-0 left-0 right-0 z-0 mx-[-16px];
55-
content: "";
55+
content: '';
5656
}
5757

5858
&:nth-child(2n):before {
@@ -63,11 +63,13 @@
6363
background-color: var(--vscode-panelStickyScroll-shadow);
6464
}
6565

66-
> div, span, button {
66+
> div,
67+
span,
68+
button {
6769
@apply z-[1];
6870
}
6971

70-
div, input {
72+
input {
7173
@apply min-h-[25px];
7274
}
7375
}
@@ -123,7 +125,7 @@
123125
}
124126

125127
.stringStyle {
126-
@apply break-all
128+
@apply break-all;
127129
}
128130

129131
.quoted {
@@ -133,7 +135,8 @@
133135
}
134136
}
135137

136-
.actionButtons, .deleteBtn {
138+
.actionButtons,
139+
.deleteBtn {
137140
@apply ml-4 flex items-center min-w-6;
138141
}
139142

@@ -149,10 +152,15 @@
149152
}
150153
}
151154

152-
.fullWidthTextArea {
153-
@apply h-[150px] w-full pb-[30px] max-w-none scroll-pb-5;
155+
.editor {
156+
@apply h-[200px] w-full pb-[30px] max-w-none scroll-pb-5;
157+
}
158+
159+
.editorWrapper {
160+
@apply h-[200px];
154161
}
155162

156-
.buttonStyle, .jsonButtonStyle {
163+
.buttonStyle,
164+
.jsonButtonStyle {
157165
@apply z-[1];
158166
}
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import '@testing-library/jest-dom/vitest'
22
import 'jsdom-worker'
3+
import React from 'react'
34

45
import { mswServer } from 'testSrc/server'
56

@@ -8,19 +9,29 @@ window.URL.revokeObjectURL = () => {}
89
window.URL.createObjectURL = () => URL
910

1011
// Mock the ResizeObserver
12+
// eslint-disable-next-line react-refresh/only-export-components
1113
const ResizeObserverMock = vi.fn(() => ({
1214
observe: vi.fn(),
1315
unobserve: vi.fn(),
1416
disconnect: vi.fn(),
1517
}))
1618

1719
vi.mock('react-virtualized-auto-sizer', async () => ({
18-
...(await vi.importActual<typeof import('react-virtualized-auto-sizer')>('react-virtualized-auto-sizer')),
19-
default: ({ children }: { children: any }) => children({ height: 600, width: 600 }),
20+
...(await vi.importActual<typeof import('react-virtualized-auto-sizer')>(
21+
'react-virtualized-auto-sizer',
22+
)),
23+
default: ({ children }: { children: any }) =>
24+
children({ height: 600, width: 600 }),
2025
}))
2126

2227
vi.mock('react-monaco-editor', () => ({
23-
default: () => null,
28+
default: ({ value, onChange, 'data-testid': dataTestId }: any) => (
29+
<textarea
30+
data-testid={dataTestId}
31+
value={value}
32+
onChange={(e) => onChange?.(e.target.value)}
33+
/>
34+
),
2435
monaco: {
2536
languages: {
2637
getLanguages: vi.fn(),

vite.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default defineConfig({
8080
globals: true,
8181
environment: 'jsdom',
8282
testTimeout: 20000,
83-
setupFiles: ['./src/webviews/test/setup.ts'],
83+
setupFiles: ['./src/webviews/test/setup.tsx'],
8484
coverage: {
8585
reporter: ['text', 'html'],
8686
reportsDirectory: './report/coverage',

0 commit comments

Comments
 (0)