Skip to content

Commit 028905d

Browse files
authored
Merge pull request #18 from qoretechnologies/feature/hash-list-field
Object editor
2 parents a27dcfc + 97088c3 commit 028905d

File tree

5 files changed

+515
-10
lines changed

5 files changed

+515
-10
lines changed

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@qoretechnologies/reqraft",
3-
"version": "0.5.1",
3+
"version": "0.6.0",
44
"description": "ReQraft is a collection of React components and hooks that are used across Qore Technologies' products made using the ReQore component library from Qore.",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -53,7 +53,7 @@
5353
"@babel/preset-typescript": "^7.12.7",
5454
"@chromatic-com/storybook": "^1.5.0",
5555
"@netsells/storybook-mockdate": "^0.3.3",
56-
"@qoretechnologies/reqore": "^0.46.6",
56+
"@qoretechnologies/reqore": "^0.47.1",
5757
"@storybook/addon-actions": "^8.1.7",
5858
"@storybook/addon-essentials": "^8.1.7",
5959
"@storybook/addon-interactions": "^8.1.7",
@@ -69,6 +69,7 @@
6969
"@testing-library/jest-dom": "^5.16.5",
7070
"@testing-library/react": "^13.4.0",
7171
"@types/jest": "^26.0.19",
72+
"@types/js-yaml": "^4.0.9",
7273
"@types/lodash": "^4.14.166",
7374
"@types/node": "^14.14.14",
7475
"@types/react": "^18.3.1",
@@ -110,6 +111,7 @@
110111
"classnames": "^2.2.6",
111112
"cronstrue": "^2.50.0",
112113
"epoch-timeago": "^1.1.9",
114+
"js-yaml": "^4.1.0",
113115
"lodash": "^4.17.21",
114116
"polished": "^4.2.2",
115117
"react-color": "^2.19.3",

src/components/form/fields/long-string/LongString.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ export const LongStringFormField = ({
1818
<ReqoreTextarea
1919
scaleWithContent
2020
fluid
21-
wrapperStyle={{
22-
width: '100%',
23-
}}
2421
onClearClick={() => {
2522
onClearClick?.();
2623
onChange?.('');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
import { StoryObj } from '@storybook/react';
2+
import { expect, fireEvent, fn } from '@storybook/test';
3+
import { useMemo, useState } from 'react';
4+
5+
import jsyaml from 'js-yaml';
6+
import { sleep, testsClickButton, testsWaitForText } from '../../../../../__tests__/utils';
7+
import { StoryMeta } from '../../../../types';
8+
import { ReqraftObjectFormField } from './Object';
9+
10+
const meta = {
11+
component: ReqraftObjectFormField,
12+
title: 'Components/Form/Object',
13+
args: {
14+
onChange: fn(),
15+
},
16+
render(args) {
17+
const [value, setValue] = useState(args.value);
18+
19+
const val = useMemo(() => {
20+
if (args.dataType === 'native' && typeof value === 'string') {
21+
if (args.resultDataType === 'yaml') {
22+
return jsyaml.load(value as string);
23+
} else if (args.resultDataType === 'json') {
24+
return JSON.parse(value as string);
25+
}
26+
}
27+
28+
return value;
29+
}, [value, args.dataType, args.resultDataType]);
30+
31+
return (
32+
<ReqraftObjectFormField
33+
{...args}
34+
value={val}
35+
onChange={(value) => {
36+
args.onChange?.(value);
37+
setValue(value);
38+
}}
39+
/>
40+
);
41+
},
42+
} as StoryMeta<typeof ReqraftObjectFormField>;
43+
44+
export default meta;
45+
type Story = StoryObj<typeof meta>;
46+
47+
export const Object: Story = {
48+
args: {
49+
type: 'object',
50+
dataType: 'json',
51+
resultDataType: 'json',
52+
},
53+
async play() {
54+
await testsWaitForText('New Object');
55+
await testsClickButton({ label: 'New Object' });
56+
await testsWaitForText('{');
57+
await testsWaitForText('}');
58+
},
59+
};
60+
61+
export const List: Story = {
62+
args: {
63+
type: 'array',
64+
dataType: 'yaml',
65+
resultDataType: 'yaml',
66+
},
67+
async play() {
68+
await testsWaitForText('New List');
69+
await testsClickButton({ label: 'New List' });
70+
await testsWaitForText('[');
71+
await testsWaitForText(']');
72+
},
73+
};
74+
75+
export const NativeOnly: Story = {
76+
args: {
77+
type: 'array',
78+
dataType: 'native',
79+
resultDataType: 'native',
80+
value: [
81+
{
82+
key: 'value',
83+
},
84+
'Test',
85+
12,
86+
false,
87+
],
88+
},
89+
async play() {
90+
await testsWaitForText('"value"');
91+
},
92+
};
93+
94+
export const ValueCanBeRemoved: Story = {
95+
args: {
96+
type: 'array',
97+
dataType: 'native',
98+
resultDataType: 'native',
99+
value: [
100+
{
101+
key: 'value',
102+
},
103+
'Test',
104+
12,
105+
false,
106+
],
107+
},
108+
async play() {
109+
await testsWaitForText('"value"');
110+
await testsClickButton({ label: 'Remove' });
111+
await testsWaitForText('New List');
112+
},
113+
};
114+
115+
export const json: Story = {
116+
args: {
117+
type: 'object',
118+
dataType: 'json',
119+
value: JSON.stringify({
120+
key: 'value',
121+
bool: false,
122+
num: 23,
123+
}),
124+
resultDataType: 'json',
125+
},
126+
async play({ args }) {
127+
await testsWaitForText('"value"');
128+
await testsClickButton({ label: 'Text' });
129+
await sleep(300);
130+
await fireEvent.change(document.querySelector('textarea'), {
131+
target: {
132+
value: JSON.stringify(
133+
{
134+
key: 'value',
135+
key2: 'value2',
136+
bool: false,
137+
num: 23,
138+
},
139+
null,
140+
2
141+
),
142+
},
143+
});
144+
await testsClickButton({ label: 'Save' });
145+
await expect(args.onChange).toHaveBeenLastCalledWith(
146+
JSON.stringify(
147+
{
148+
key: 'value',
149+
key2: 'value2',
150+
bool: false,
151+
num: 23,
152+
},
153+
null,
154+
2
155+
)
156+
);
157+
await testsClickButton({ label: 'Editor' });
158+
await testsWaitForText('"value2"');
159+
},
160+
};
161+
162+
export const yaml: Story = {
163+
args: {
164+
type: 'object',
165+
dataType: 'yaml',
166+
value: jsyaml.dump({
167+
key: 'value',
168+
bool: false,
169+
num: 23,
170+
}),
171+
resultDataType: 'yaml',
172+
},
173+
async play({ args }) {
174+
await testsWaitForText('"value"');
175+
await testsClickButton({ label: 'Text' });
176+
await sleep(300);
177+
await fireEvent.change(document.querySelector('textarea'), {
178+
target: {
179+
value: jsyaml.dump({
180+
key: 'value',
181+
key2: 'value2',
182+
bool: false,
183+
num: 23,
184+
}),
185+
},
186+
});
187+
await testsClickButton({ label: 'Save' });
188+
await expect(args.onChange).toHaveBeenLastCalledWith(
189+
'key: value\nkey2: value2\nbool: false\nnum: 23\n'
190+
);
191+
await testsClickButton({ label: 'Editor' });
192+
await testsWaitForText('"value2"');
193+
},
194+
};
195+
196+
export const YamlToJson: Story = {
197+
args: {
198+
type: 'object',
199+
dataType: 'yaml',
200+
value: jsyaml.dump({
201+
key: 'value',
202+
bool: false,
203+
num: 23,
204+
}),
205+
resultDataType: 'json',
206+
},
207+
async play({ args }) {
208+
await testsWaitForText('"value"');
209+
await testsClickButton({ label: 'Text' });
210+
await sleep(300);
211+
await fireEvent.change(document.querySelector('textarea'), {
212+
target: {
213+
value: jsyaml.dump({
214+
key: 'value',
215+
key2: 'value2',
216+
bool: false,
217+
num: 23,
218+
}),
219+
},
220+
});
221+
await testsClickButton({ label: 'Save' });
222+
await expect(args.onChange).toHaveBeenLastCalledWith(
223+
'{\n "key": "value",\n "key2": "value2",\n "bool": false,\n "num": 23\n}'
224+
);
225+
await testsClickButton({ label: 'Editor' });
226+
await testsWaitForText('"value2"');
227+
},
228+
};
229+
230+
export const NativeToYaml: Story = {
231+
args: {
232+
type: 'object',
233+
dataType: 'native',
234+
value: {
235+
key: 'value',
236+
bool: false,
237+
num: 23,
238+
},
239+
resultDataType: 'yaml',
240+
},
241+
async play({ args }) {
242+
await testsWaitForText('"value"');
243+
await testsClickButton({ label: 'Text' });
244+
await sleep(300);
245+
await fireEvent.change(document.querySelector('textarea'), {
246+
target: {
247+
value: jsyaml.dump({
248+
key: 'value',
249+
key2: 'value2',
250+
bool: false,
251+
num: 23,
252+
}),
253+
},
254+
});
255+
await testsClickButton({ label: 'Save' });
256+
await expect(args.onChange).toHaveBeenLastCalledWith(
257+
jsyaml.dump({
258+
key: 'value',
259+
key2: 'value2',
260+
bool: false,
261+
num: 23,
262+
})
263+
);
264+
await testsClickButton({ label: 'Editor' });
265+
await testsWaitForText('"value2"');
266+
},
267+
};

0 commit comments

Comments
 (0)