@truedat/df 8.3.6 → 8.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/components/FieldViewerValue.js +3 -1
- package/src/components/__tests__/DynamicForm.spec.js +89 -0
- package/src/components/__tests__/DynamicFormViewer.spec.js +40 -0
- package/src/components/__tests__/DynamicFormWithTranslations.spec.js +122 -0
- package/src/components/__tests__/EditableDynamicFieldValue.spec.js +73 -0
- package/src/components/__tests__/FieldViewerValue.spec.js +19 -0
- package/src/components/widgets/FieldByWidget.js +3 -0
- package/src/components/widgets/MarkdownField.js +14 -0
- package/src/components/widgets/__tests__/DynamicField.spec.js +26 -1
- package/src/templates/components/templateForm/__tests__/__snapshots__/ActiveGroupForm.spec.js.snap +17 -0
- package/src/templates/components/templateForm/__tests__/__snapshots__/FieldDefinition.spec.js.snap +17 -0
- package/src/templates/components/templateForm/__tests__/__snapshots__/FieldForm.spec.js.snap +51 -0
- package/src/templates/components/templateForm/__tests__/__snapshots__/TemplateForm.spec.js.snap +34 -0
- package/src/templates/components/templateForm/valueDefinitions.js +2 -1
- package/src/templates/components/templateForm/widgetDefinitions.js +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/df",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.1",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -51,14 +51,14 @@
|
|
|
51
51
|
"@testing-library/jest-dom": "^6.6.3",
|
|
52
52
|
"@testing-library/react": "^16.3.0",
|
|
53
53
|
"@testing-library/user-event": "^14.6.1",
|
|
54
|
-
"@truedat/test": "8.
|
|
54
|
+
"@truedat/test": "8.4.1",
|
|
55
55
|
"identity-obj-proxy": "^3.0.0",
|
|
56
56
|
"jest": "^29.7.0",
|
|
57
57
|
"redux-saga-test-plan": "^4.0.6"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@apollo/client": "^3.13.8",
|
|
61
|
-
"@truedat/core": "8.
|
|
61
|
+
"@truedat/core": "8.4.1",
|
|
62
62
|
"axios": "^1.13.5",
|
|
63
63
|
"graphql": "^16.11.0",
|
|
64
64
|
"is-hotkey": "^0.2.0",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"semantic-ui-react": "^3.0.0-beta.2",
|
|
88
88
|
"swr": "^2.3.3"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "fc56d67c36dfe2d5db692b26ebdd2071b7518e1f"
|
|
91
91
|
}
|
|
@@ -2,7 +2,7 @@ import _ from "lodash";
|
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
4
|
import { Icon, Label, Table } from "semantic-ui-react";
|
|
5
|
-
import { SafeLink, RichTextEditor } from "@truedat/core/components";
|
|
5
|
+
import { MarkdownReader, SafeLink, RichTextEditor } from "@truedat/core/components";
|
|
6
6
|
import ImagePreview from "./widgets/ImagePreview";
|
|
7
7
|
import SystemPreview from "./widgets/SystemPreview";
|
|
8
8
|
import "../styles/fieldGroupDetail.less";
|
|
@@ -56,6 +56,8 @@ export const FieldViewerValue = ({
|
|
|
56
56
|
);
|
|
57
57
|
case "enriched_text":
|
|
58
58
|
return <RichTextEditor readOnly value={value} />;
|
|
59
|
+
case "markdown":
|
|
60
|
+
return <MarkdownReader content={value} />;
|
|
59
61
|
case "table":
|
|
60
62
|
return (
|
|
61
63
|
<Table style={{ marginTop: "10px" }} celled striped compact fixed>
|
|
@@ -1,6 +1,31 @@
|
|
|
1
|
+
import { fireEvent, waitFor } from "@testing-library/react";
|
|
1
2
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
3
|
import { DynamicForm } from "../DynamicForm";
|
|
3
4
|
|
|
5
|
+
jest.mock("../widgets/FieldByWidget", () => ({
|
|
6
|
+
__esModule: true,
|
|
7
|
+
default: ({ field, onChange }) => {
|
|
8
|
+
if (field?.widget !== "markdown") {
|
|
9
|
+
const actual = jest.requireActual("../widgets/FieldByWidget");
|
|
10
|
+
return actual.default({ field, onChange });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<button
|
|
15
|
+
type="button"
|
|
16
|
+
onClick={() =>
|
|
17
|
+
onChange?.(null, {
|
|
18
|
+
name: field?.name,
|
|
19
|
+
value: `${field?.value || ""} updated`,
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
>
|
|
23
|
+
Edit markdown
|
|
24
|
+
</button>
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
|
|
4
29
|
describe("<DynamicForm />", () => {
|
|
5
30
|
const applyTemplate = jest.fn(),
|
|
6
31
|
onChange = jest.fn(),
|
|
@@ -162,4 +187,68 @@ describe("<DynamicForm />", () => {
|
|
|
162
187
|
await waitForLoad(rendered);
|
|
163
188
|
expect(rendered.container.querySelector(".field-group-segment")).toBeNull();
|
|
164
189
|
});
|
|
190
|
+
|
|
191
|
+
it("sends updated markdown string to onChange payload", async () => {
|
|
192
|
+
const applyTemplate = jest.fn((content) => content);
|
|
193
|
+
const onChange = jest.fn();
|
|
194
|
+
|
|
195
|
+
const template = {
|
|
196
|
+
scope: "bg",
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
name: "g1",
|
|
200
|
+
fields: [
|
|
201
|
+
{
|
|
202
|
+
name: "md-field",
|
|
203
|
+
label: "md-label",
|
|
204
|
+
type: "markdown",
|
|
205
|
+
widget: "markdown",
|
|
206
|
+
cardinality: "1",
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const initialMarkdown = `## Initial
|
|
214
|
+
|
|
215
|
+
_Now you can use:_
|
|
216
|
+
|
|
217
|
+
* Lists
|
|
218
|
+
|
|
219
|
+
[Links](https://example.com)
|
|
220
|
+
|
|
221
|
+
**Bold**
|
|
222
|
+
|
|
223
|
+
_Italic_`;
|
|
224
|
+
|
|
225
|
+
const content = {
|
|
226
|
+
"md-field": { value: initialMarkdown, origin: "user" },
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const rendered = render(
|
|
230
|
+
<DynamicForm
|
|
231
|
+
applyTemplate={applyTemplate}
|
|
232
|
+
content={content}
|
|
233
|
+
onChange={onChange}
|
|
234
|
+
template={template}
|
|
235
|
+
/>,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
await waitForLoad(rendered);
|
|
239
|
+
onChange.mockClear();
|
|
240
|
+
|
|
241
|
+
fireEvent.click(rendered.getByText(/edit markdown/i));
|
|
242
|
+
|
|
243
|
+
await waitFor(() => {
|
|
244
|
+
expect(onChange).toHaveBeenCalled();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
expect(onChange).toHaveBeenLastCalledWith({
|
|
248
|
+
"md-field": {
|
|
249
|
+
value: `${initialMarkdown} updated`,
|
|
250
|
+
origin: "user",
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
});
|
|
165
254
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { render } from "@truedat/test/render";
|
|
2
|
+
import { DynamicFormViewer } from "../DynamicFormViewer";
|
|
3
|
+
import { markdownToHtml } from "@truedat/core/components/Markdown";
|
|
4
|
+
|
|
5
|
+
describe("<DynamicFormViewer />", () => {
|
|
6
|
+
it("renders markdown content through MarkdownReader", () => {
|
|
7
|
+
const markdown = "## Title\n\n**Hello** world\n\n[link](https://example.com)";
|
|
8
|
+
|
|
9
|
+
const template = {
|
|
10
|
+
scope: "bg",
|
|
11
|
+
content: [
|
|
12
|
+
{
|
|
13
|
+
name: "g1",
|
|
14
|
+
fields: [
|
|
15
|
+
{
|
|
16
|
+
name: "md-field",
|
|
17
|
+
label: "md-label",
|
|
18
|
+
type: "markdown",
|
|
19
|
+
widget: "markdown",
|
|
20
|
+
cardinality: "1",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const content = {
|
|
28
|
+
"md-field": { value: markdown, origin: "user" },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const { container } = render(
|
|
32
|
+
<DynamicFormViewer template={template} content={content} />
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const reader = container.querySelector(".markdown-reader");
|
|
36
|
+
expect(reader).toBeInTheDocument();
|
|
37
|
+
expect(reader.innerHTML).toBe(markdownToHtml(markdown));
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { fireEvent, waitFor } from "@testing-library/react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import { DynamicFormWithTranslations } from "../DynamicFormWithTranslations";
|
|
4
|
+
|
|
5
|
+
jest.mock("@truedat/core/i18n", () => {
|
|
6
|
+
const originalModule = jest.requireActual("@truedat/core/i18n");
|
|
7
|
+
return {
|
|
8
|
+
__esModule: true,
|
|
9
|
+
...originalModule,
|
|
10
|
+
useLanguage: () => ({
|
|
11
|
+
defaultLang: "es",
|
|
12
|
+
altLangs: ["es", "en"],
|
|
13
|
+
requiredLangs: ["es", "en"],
|
|
14
|
+
enabledLangs: ["es", "en"],
|
|
15
|
+
isMultilingual: true,
|
|
16
|
+
setAltLang: jest.fn(),
|
|
17
|
+
altLang: "en",
|
|
18
|
+
getMessagesForLang: () => ({}),
|
|
19
|
+
lang: "es",
|
|
20
|
+
loading: false,
|
|
21
|
+
locales: [],
|
|
22
|
+
localesError: null,
|
|
23
|
+
mutate: jest.fn(),
|
|
24
|
+
onIntlError: () => {},
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
jest.mock("../widgets/FieldByWidget", () => ({
|
|
30
|
+
__esModule: true,
|
|
31
|
+
default: ({ field, onChange }) => (
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
onClick={() =>
|
|
35
|
+
onChange?.(null, {
|
|
36
|
+
name: field?.name,
|
|
37
|
+
value: `${field?.value || ""} updated`,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
>
|
|
41
|
+
Edit markdown
|
|
42
|
+
</button>
|
|
43
|
+
),
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
jest.mock("@truedat/core/components", () => {
|
|
47
|
+
const originalModule = jest.requireActual("@truedat/core/components");
|
|
48
|
+
return {
|
|
49
|
+
__esModule: true,
|
|
50
|
+
...originalModule,
|
|
51
|
+
LanguagesTabs: () => null,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("<DynamicFormWithTranslations /> markdown", () => {
|
|
56
|
+
it("calls onChange with the updated markdown per language", async () => {
|
|
57
|
+
const applyTemplate = jest.fn((content) => content);
|
|
58
|
+
const onChange = jest.fn();
|
|
59
|
+
|
|
60
|
+
const template = {
|
|
61
|
+
scope: "bg",
|
|
62
|
+
name: "tmpl",
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
name: "g1",
|
|
66
|
+
fields: [
|
|
67
|
+
{
|
|
68
|
+
name: "md-field",
|
|
69
|
+
label: "md-label",
|
|
70
|
+
type: "markdown",
|
|
71
|
+
widget: "markdown",
|
|
72
|
+
cardinality: "1",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const i18nContent = {
|
|
80
|
+
es: { "md-field": { value: "## ES", origin: "user" } },
|
|
81
|
+
en: { "md-field": { value: "## EN", origin: "user" } },
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const rendered = render(
|
|
85
|
+
<DynamicFormWithTranslations
|
|
86
|
+
applyTemplate={applyTemplate}
|
|
87
|
+
i18nContent={i18nContent}
|
|
88
|
+
onChange={onChange}
|
|
89
|
+
template={template}
|
|
90
|
+
/>,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const buttons = rendered.getAllByText(/edit markdown/i);
|
|
94
|
+
expect(buttons.length).toBe(2);
|
|
95
|
+
|
|
96
|
+
fireEvent.click(buttons[0]);
|
|
97
|
+
fireEvent.click(buttons[1]);
|
|
98
|
+
|
|
99
|
+
await waitFor(() => {
|
|
100
|
+
expect(onChange).toHaveBeenCalled();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const calls = onChange.mock.calls;
|
|
104
|
+
const esCall = calls.find(([lang]) => lang === "es");
|
|
105
|
+
const enCall = calls.find(([lang]) => lang === "en");
|
|
106
|
+
|
|
107
|
+
expect(esCall).toBeTruthy();
|
|
108
|
+
expect(esCall[1]).toEqual({
|
|
109
|
+
content: {
|
|
110
|
+
"md-field": { value: "## ES updated", origin: "user" },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
expect(enCall).toBeTruthy();
|
|
115
|
+
expect(enCall[1]).toEqual({
|
|
116
|
+
content: {
|
|
117
|
+
"md-field": { value: "## EN updated", origin: "user" },
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { waitFor } from "@testing-library/react";
|
|
1
2
|
import { render } from "@truedat/test/render";
|
|
3
|
+
import { markdownToHtml } from "@truedat/core/components/Markdown";
|
|
2
4
|
import { EditableDynamicFieldValue } from "../EditableDynamicFieldValue";
|
|
3
5
|
|
|
4
6
|
describe("<EditableDynamicFieldValue />", () => {
|
|
@@ -33,4 +35,75 @@ describe("<EditableDynamicFieldValue />", () => {
|
|
|
33
35
|
);
|
|
34
36
|
expect(wrapper).toMatchSnapshot();
|
|
35
37
|
});
|
|
38
|
+
|
|
39
|
+
it("renders MarkdownReader when not editing", () => {
|
|
40
|
+
const markdown = "## Title\n\n**Hello** world";
|
|
41
|
+
|
|
42
|
+
const getEditFunctions = ({
|
|
43
|
+
editingField,
|
|
44
|
+
setEditingField = jest.fn(),
|
|
45
|
+
onChange = jest.fn(),
|
|
46
|
+
}) => ({
|
|
47
|
+
onChange,
|
|
48
|
+
onCancel: jest.fn(),
|
|
49
|
+
onSubmit: jest.fn(),
|
|
50
|
+
editingField,
|
|
51
|
+
setEditingField,
|
|
52
|
+
updateStatus: "none",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const props = {
|
|
56
|
+
label: "md-label",
|
|
57
|
+
name: "md-field",
|
|
58
|
+
value: { value: markdown, origin: "user" },
|
|
59
|
+
type: "markdown",
|
|
60
|
+
values: null,
|
|
61
|
+
widget: "markdown",
|
|
62
|
+
isSecret: false,
|
|
63
|
+
isChanged: false,
|
|
64
|
+
editFunctions: getEditFunctions({ editingField: "other" }),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const { container } = render(<EditableDynamicFieldValue {...props} />);
|
|
68
|
+
const reader = container.querySelector(".markdown-reader");
|
|
69
|
+
expect(reader).toBeInTheDocument();
|
|
70
|
+
expect(reader.innerHTML).toBe(markdownToHtml(markdown));
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("renders MarkdownEditor when editing", async () => {
|
|
74
|
+
const markdown = "## Title\n\n**Hello** world";
|
|
75
|
+
|
|
76
|
+
const getEditFunctions = ({
|
|
77
|
+
editingField,
|
|
78
|
+
setEditingField = jest.fn(),
|
|
79
|
+
onChange = jest.fn(),
|
|
80
|
+
}) => ({
|
|
81
|
+
onChange,
|
|
82
|
+
onCancel: jest.fn(),
|
|
83
|
+
onSubmit: jest.fn(),
|
|
84
|
+
editingField,
|
|
85
|
+
setEditingField,
|
|
86
|
+
updateStatus: "none",
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const props = {
|
|
90
|
+
label: "md-label",
|
|
91
|
+
name: "md-field",
|
|
92
|
+
value: { value: markdown, origin: "user" },
|
|
93
|
+
type: "markdown",
|
|
94
|
+
values: null,
|
|
95
|
+
widget: "markdown",
|
|
96
|
+
isSecret: false,
|
|
97
|
+
isChanged: false,
|
|
98
|
+
editFunctions: getEditFunctions({ editingField: "md-field" }),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const { container } = render(<EditableDynamicFieldValue {...props} />);
|
|
102
|
+
|
|
103
|
+
await waitFor(() => {
|
|
104
|
+
expect(container.querySelector(".markdown-editor")).toBeInTheDocument();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(container.querySelector(".tiptap")).toBeInTheDocument();
|
|
108
|
+
});
|
|
36
109
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { render } from "@truedat/test/render";
|
|
2
2
|
import { FieldViewerValue } from "../FieldViewerValue";
|
|
3
|
+
import { markdownToHtml } from "@truedat/core/components/Markdown";
|
|
3
4
|
|
|
4
5
|
describe("<FieldViewerValue />", () => {
|
|
5
6
|
const testTypes = [
|
|
@@ -78,4 +79,22 @@ describe("<FieldViewerValue />", () => {
|
|
|
78
79
|
const { container } = render(<FieldViewerValue {...props} />);
|
|
79
80
|
expect(container).toMatchSnapshot();
|
|
80
81
|
});
|
|
82
|
+
|
|
83
|
+
it("renders MarkdownReader for type=markdown", () => {
|
|
84
|
+
const markdown = "## Title\n\n**Hello** world\n\n[link](https://example.com)";
|
|
85
|
+
const { container } = render(
|
|
86
|
+
<FieldViewerValue type="markdown" value={markdown} label="md" widget="markdown" />,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const reader = container.querySelector(".markdown-reader");
|
|
90
|
+
expect(reader).toBeInTheDocument();
|
|
91
|
+
expect(reader.innerHTML).toBe(markdownToHtml(markdown));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns null when markdown content is empty", () => {
|
|
95
|
+
const { container } = render(
|
|
96
|
+
<FieldViewerValue type="markdown" value=" " label="md" widget="markdown" />,
|
|
97
|
+
);
|
|
98
|
+
expect(container.firstChild).toBeNull();
|
|
99
|
+
});
|
|
81
100
|
});
|
|
@@ -6,6 +6,7 @@ import DropdownField from "./DropdownField";
|
|
|
6
6
|
import EnrichedTextField from "./EnrichedTextField";
|
|
7
7
|
import IdentifierField from "./IdentifierField";
|
|
8
8
|
import ImageField from "./ImageField";
|
|
9
|
+
import MarkdownField from "./MarkdownField";
|
|
9
10
|
import PairListField from "./PairListField";
|
|
10
11
|
import PasswordField from "./PasswordField";
|
|
11
12
|
import RadioField from "./RadioField";
|
|
@@ -34,6 +35,8 @@ const FieldByWidget = ({ scope, widget, onChange, field }) => {
|
|
|
34
35
|
return <PairListField field={field} onChange={onChange} />;
|
|
35
36
|
case "enriched_text":
|
|
36
37
|
return <EnrichedTextField field={field} onChange={onChange} />;
|
|
38
|
+
case "markdown":
|
|
39
|
+
return <MarkdownField field={field} onChange={onChange} />;
|
|
37
40
|
case "table":
|
|
38
41
|
return <TableField field={field} onChange={onChange} />;
|
|
39
42
|
case "dynamic_table":
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
2
|
+
import { MarkdownEditor } from "@truedat/core/components";
|
|
3
|
+
|
|
4
|
+
export const MarkdownField = ({ field: { name, value }, onChange }) => (
|
|
5
|
+
<MarkdownEditor name={name} value={value || ""} onChange={onChange} />
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
MarkdownField.propTypes = {
|
|
9
|
+
field: PropTypes.object,
|
|
10
|
+
onChange: PropTypes.func,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default MarkdownField;
|
|
14
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
-
import { within } from "@testing-library/react";
|
|
2
|
+
import { within, waitFor } from "@testing-library/react";
|
|
3
3
|
import { DynamicField } from "../DynamicField";
|
|
4
4
|
|
|
5
5
|
const onChange = jest.fn();
|
|
@@ -155,4 +155,29 @@ describe("<DynamicField />", () => {
|
|
|
155
155
|
await waitForLoad(rendered);
|
|
156
156
|
expect(rendered.container).toMatchSnapshot();
|
|
157
157
|
});
|
|
158
|
+
|
|
159
|
+
it("renders MarkdownEditor for widget=markdown", async () => {
|
|
160
|
+
const props = {
|
|
161
|
+
field: {
|
|
162
|
+
widget: "markdown",
|
|
163
|
+
type: "markdown",
|
|
164
|
+
name: "md-field",
|
|
165
|
+
label: "Markdown field",
|
|
166
|
+
description: null,
|
|
167
|
+
cardinality: "1",
|
|
168
|
+
value: { value: "**Bold** text", origin: "user" },
|
|
169
|
+
editable: true,
|
|
170
|
+
disabled: false,
|
|
171
|
+
},
|
|
172
|
+
onChange: jest.fn(),
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const { container } = render(<DynamicField {...props} />);
|
|
176
|
+
|
|
177
|
+
await waitFor(() => {
|
|
178
|
+
expect(container.querySelector(".markdown-editor")).toBeInTheDocument();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(container.querySelector(".tiptap")).toBeInTheDocument();
|
|
182
|
+
});
|
|
158
183
|
});
|
package/src/templates/components/templateForm/__tests__/__snapshots__/ActiveGroupForm.spec.js.snap
CHANGED
|
@@ -426,6 +426,23 @@ exports[`<ActiveGroupForm /> matches the latest snapshot 1`] = `
|
|
|
426
426
|
Enrichedtext
|
|
427
427
|
</span>
|
|
428
428
|
</div>
|
|
429
|
+
<div
|
|
430
|
+
aria-checked="false"
|
|
431
|
+
aria-selected="false"
|
|
432
|
+
class="item"
|
|
433
|
+
role="option"
|
|
434
|
+
style="pointer-events: all;"
|
|
435
|
+
>
|
|
436
|
+
<i
|
|
437
|
+
aria-hidden="true"
|
|
438
|
+
class="text cursor icon"
|
|
439
|
+
/>
|
|
440
|
+
<span
|
|
441
|
+
class="text"
|
|
442
|
+
>
|
|
443
|
+
Markdown
|
|
444
|
+
</span>
|
|
445
|
+
</div>
|
|
429
446
|
<div
|
|
430
447
|
aria-checked="false"
|
|
431
448
|
aria-selected="false"
|
package/src/templates/components/templateForm/__tests__/__snapshots__/FieldDefinition.spec.js.snap
CHANGED
|
@@ -187,6 +187,23 @@ exports[`FieldDefinition renders dropdowns with initial values 1`] = `
|
|
|
187
187
|
Enrichedtext
|
|
188
188
|
</span>
|
|
189
189
|
</div>
|
|
190
|
+
<div
|
|
191
|
+
aria-checked="false"
|
|
192
|
+
aria-selected="false"
|
|
193
|
+
class="item"
|
|
194
|
+
role="option"
|
|
195
|
+
style="pointer-events: all;"
|
|
196
|
+
>
|
|
197
|
+
<i
|
|
198
|
+
aria-hidden="true"
|
|
199
|
+
class="text cursor icon"
|
|
200
|
+
/>
|
|
201
|
+
<span
|
|
202
|
+
class="text"
|
|
203
|
+
>
|
|
204
|
+
Markdown
|
|
205
|
+
</span>
|
|
206
|
+
</div>
|
|
190
207
|
<div
|
|
191
208
|
aria-checked="false"
|
|
192
209
|
aria-selected="false"
|
package/src/templates/components/templateForm/__tests__/__snapshots__/FieldForm.spec.js.snap
CHANGED
|
@@ -353,6 +353,23 @@ exports[`<FieldForm /> matches the latest snapshot 1`] = `
|
|
|
353
353
|
Enrichedtext
|
|
354
354
|
</span>
|
|
355
355
|
</div>
|
|
356
|
+
<div
|
|
357
|
+
aria-checked="false"
|
|
358
|
+
aria-selected="false"
|
|
359
|
+
class="item"
|
|
360
|
+
role="option"
|
|
361
|
+
style="pointer-events: all;"
|
|
362
|
+
>
|
|
363
|
+
<i
|
|
364
|
+
aria-hidden="true"
|
|
365
|
+
class="text cursor icon"
|
|
366
|
+
/>
|
|
367
|
+
<span
|
|
368
|
+
class="text"
|
|
369
|
+
>
|
|
370
|
+
Markdown
|
|
371
|
+
</span>
|
|
372
|
+
</div>
|
|
356
373
|
<div
|
|
357
374
|
aria-checked="false"
|
|
358
375
|
aria-selected="false"
|
|
@@ -1049,6 +1066,23 @@ exports[`<FieldForm /> renders MandatoryConditional 1`] = `
|
|
|
1049
1066
|
Enrichedtext
|
|
1050
1067
|
</span>
|
|
1051
1068
|
</div>
|
|
1069
|
+
<div
|
|
1070
|
+
aria-checked="false"
|
|
1071
|
+
aria-selected="false"
|
|
1072
|
+
class="item"
|
|
1073
|
+
role="option"
|
|
1074
|
+
style="pointer-events: all;"
|
|
1075
|
+
>
|
|
1076
|
+
<i
|
|
1077
|
+
aria-hidden="true"
|
|
1078
|
+
class="text cursor icon"
|
|
1079
|
+
/>
|
|
1080
|
+
<span
|
|
1081
|
+
class="text"
|
|
1082
|
+
>
|
|
1083
|
+
Markdown
|
|
1084
|
+
</span>
|
|
1085
|
+
</div>
|
|
1052
1086
|
<div
|
|
1053
1087
|
aria-checked="false"
|
|
1054
1088
|
aria-selected="false"
|
|
@@ -1899,6 +1933,23 @@ exports[`<FieldForm /> renders ValuesField and manages onChange 1`] = `
|
|
|
1899
1933
|
Enrichedtext
|
|
1900
1934
|
</span>
|
|
1901
1935
|
</div>
|
|
1936
|
+
<div
|
|
1937
|
+
aria-checked="false"
|
|
1938
|
+
aria-selected="false"
|
|
1939
|
+
class="item"
|
|
1940
|
+
role="option"
|
|
1941
|
+
style="pointer-events: all;"
|
|
1942
|
+
>
|
|
1943
|
+
<i
|
|
1944
|
+
aria-hidden="true"
|
|
1945
|
+
class="text cursor icon"
|
|
1946
|
+
/>
|
|
1947
|
+
<span
|
|
1948
|
+
class="text"
|
|
1949
|
+
>
|
|
1950
|
+
Markdown
|
|
1951
|
+
</span>
|
|
1952
|
+
</div>
|
|
1902
1953
|
<div
|
|
1903
1954
|
aria-checked="false"
|
|
1904
1955
|
aria-selected="false"
|
package/src/templates/components/templateForm/__tests__/__snapshots__/TemplateForm.spec.js.snap
CHANGED
|
@@ -697,6 +697,23 @@ exports[`<TemplateForm /> matches snapshot when scope has no relations 1`] = `
|
|
|
697
697
|
Enrichedtext
|
|
698
698
|
</span>
|
|
699
699
|
</div>
|
|
700
|
+
<div
|
|
701
|
+
aria-checked="false"
|
|
702
|
+
aria-selected="false"
|
|
703
|
+
class="item"
|
|
704
|
+
role="option"
|
|
705
|
+
style="pointer-events: all;"
|
|
706
|
+
>
|
|
707
|
+
<i
|
|
708
|
+
aria-hidden="true"
|
|
709
|
+
class="text cursor icon"
|
|
710
|
+
/>
|
|
711
|
+
<span
|
|
712
|
+
class="text"
|
|
713
|
+
>
|
|
714
|
+
Markdown
|
|
715
|
+
</span>
|
|
716
|
+
</div>
|
|
700
717
|
<div
|
|
701
718
|
aria-checked="false"
|
|
702
719
|
aria-selected="false"
|
|
@@ -1792,6 +1809,23 @@ exports[`<TemplateForm /> matches snapshot when scope has relations 1`] = `
|
|
|
1792
1809
|
Enrichedtext
|
|
1793
1810
|
</span>
|
|
1794
1811
|
</div>
|
|
1812
|
+
<div
|
|
1813
|
+
aria-checked="false"
|
|
1814
|
+
aria-selected="false"
|
|
1815
|
+
class="item"
|
|
1816
|
+
role="option"
|
|
1817
|
+
style="pointer-events: all;"
|
|
1818
|
+
>
|
|
1819
|
+
<i
|
|
1820
|
+
aria-hidden="true"
|
|
1821
|
+
class="text cursor icon"
|
|
1822
|
+
/>
|
|
1823
|
+
<span
|
|
1824
|
+
class="text"
|
|
1825
|
+
>
|
|
1826
|
+
Markdown
|
|
1827
|
+
</span>
|
|
1828
|
+
</div>
|
|
1795
1829
|
<div
|
|
1796
1830
|
aria-checked="false"
|
|
1797
1831
|
aria-selected="false"
|
|
@@ -28,6 +28,7 @@ const eligibleValues = {
|
|
|
28
28
|
pair_list: { url: [null] }, // Links
|
|
29
29
|
color_picker: { string: [null] },
|
|
30
30
|
enriched_text: { enriched_text: [null] },
|
|
31
|
+
markdown: { markdown: [null] },
|
|
31
32
|
table: { table: ["table_columns"] },
|
|
32
33
|
dynamic_table: { dynamic_table: ["table_columns"] },
|
|
33
34
|
password: { string: [null] },
|
|
@@ -55,7 +56,7 @@ export const valuesSelector = (type) =>
|
|
|
55
56
|
export const valueSegment = (values, type, fieldType) =>
|
|
56
57
|
_.size(values) > 1 || valuesSelector(type) || defaultValue(type, fieldType);
|
|
57
58
|
|
|
58
|
-
export const hasAiSuggestions = (fieldType, keyType) => _.includes(fieldType)(["string", "enriched_text"]) &&
|
|
59
|
+
export const hasAiSuggestions = (fieldType, keyType) => _.includes(fieldType)(["string", "enriched_text", "markdown"]) &&
|
|
59
60
|
_.includes(keyType)(["fixed", "fixed_tuple", undefined]);
|
|
60
61
|
|
|
61
62
|
const typeFromKey = (keys) =>
|
|
@@ -108,6 +108,14 @@ export const WIDGETS = [
|
|
|
108
108
|
cardinalities: ["?", "1"],
|
|
109
109
|
types: ["enriched_text"],
|
|
110
110
|
},
|
|
111
|
+
{
|
|
112
|
+
key: "markdown",
|
|
113
|
+
value: "markdown",
|
|
114
|
+
text: "Markdown",
|
|
115
|
+
icon: "text cursor",
|
|
116
|
+
cardinalities: ["?", "1"],
|
|
117
|
+
types: ["markdown"],
|
|
118
|
+
},
|
|
111
119
|
{
|
|
112
120
|
key: "table",
|
|
113
121
|
value: "table",
|