@openmrs/esm-form-builder-app 2.0.2-pre.574 → 2.0.2-pre.586
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/README.md +43 -17
- package/dist/127.js +1 -1
- package/dist/127.js.map +1 -1
- package/dist/150.js +1 -1
- package/dist/150.js.map +1 -1
- package/dist/153.js +1 -1
- package/dist/153.js.map +1 -1
- package/dist/164.js +1 -1
- package/dist/256.js +1 -1
- package/dist/319.js +1 -1
- package/dist/447.js +1 -1
- package/dist/447.js.map +1 -1
- package/dist/515.js +2 -0
- package/dist/{773.js.LICENSE.txt → 515.js.LICENSE.txt} +9 -0
- package/dist/515.js.map +1 -0
- package/dist/527.js +1 -0
- package/dist/527.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/757.js +1 -1
- package/dist/788.js +1 -1
- package/dist/800.js +1 -1
- package/dist/800.js.map +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/878.js +2 -0
- package/dist/{208.js.LICENSE.txt → 878.js.LICENSE.txt} +2 -1
- package/dist/878.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-form-builder-app.js +1 -1
- package/dist/openmrs-esm-form-builder-app.js.buildmanifest.json +154 -175
- package/dist/openmrs-esm-form-builder-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +35 -32
- package/src/components/action-buttons/action-buttons.component.tsx +65 -101
- package/src/components/dashboard/dashboard.component.tsx +98 -174
- package/src/components/dashboard/dashboard.test.tsx +51 -81
- package/src/components/empty-state/empty-data-illustration.component.tsx +4 -16
- package/src/components/empty-state/empty-state.component.tsx +11 -15
- package/src/components/error-state/error-state.component.tsx +11 -13
- package/src/components/form-editor/form-editor.component.tsx +97 -128
- package/src/components/form-renderer/form-renderer.component.tsx +30 -41
- package/src/components/interactive-builder/add-question-modal.component.tsx +129 -167
- package/src/components/interactive-builder/delete-page-modal.component.tsx +24 -37
- package/src/components/interactive-builder/delete-question-modal.component.tsx +25 -47
- package/src/components/interactive-builder/delete-section-modal.component.tsx +24 -37
- package/src/components/interactive-builder/draggable-question.component.tsx +21 -34
- package/src/components/interactive-builder/droppable-container.component.tsx +5 -5
- package/src/components/interactive-builder/edit-question-modal.component.tsx +191 -233
- package/src/components/interactive-builder/editable-value.component.tsx +12 -17
- package/src/components/interactive-builder/interactive-builder.component.tsx +134 -184
- package/src/components/interactive-builder/new-form-modal.component.tsx +35 -49
- package/src/components/interactive-builder/page-modal.component.tsx +29 -45
- package/src/components/interactive-builder/question-modal.scss +7 -0
- package/src/components/interactive-builder/section-modal.component.tsx +29 -40
- package/src/components/interactive-builder/value-editor.component.tsx +11 -16
- package/src/components/modals/save-form-modal.component.tsx +112 -165
- package/src/components/pagination/index.ts +2 -2
- package/src/components/pagination/pagination.component.tsx +8 -13
- package/src/components/pagination/usePaginationInfo.ts +4 -9
- package/src/components/schema-editor/schema-editor.component.tsx +11 -17
- package/src/config-schema.ts +28 -30
- package/src/declarations.d.ts +4 -3
- package/src/form-builder-admin-card-link.component.tsx +7 -11
- package/src/forms.resource.ts +66 -87
- package/src/hooks/useClobdata.ts +10 -12
- package/src/hooks/useConceptLookup.ts +5 -8
- package/src/hooks/useConceptName.ts +6 -9
- package/src/hooks/useEncounterTypes.ts +8 -8
- package/src/hooks/useForm.ts +7 -7
- package/src/hooks/useForms.ts +5 -8
- package/src/index.ts +11 -23
- package/src/root.component.tsx +4 -4
- package/src/setup-tests.ts +1 -9
- package/src/test-helpers.tsx +8 -15
- package/src/types.ts +16 -8
- package/dist/208.js +0 -2
- package/dist/208.js.map +0 -1
- package/dist/536.js +0 -1
- package/dist/536.js.map +0 -1
- package/dist/62.js +0 -1
- package/dist/62.js.map +0 -1
- package/dist/773.js +0 -2
- package/dist/773.js.map +0 -1
- package/src/constants.ts +0 -3
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { screen, waitFor } from
|
|
3
|
-
import userEvent from
|
|
4
|
-
import { navigate, openmrsFetch, usePagination } from
|
|
5
|
-
import { renderWithSwr, waitForLoadingToFinish } from
|
|
6
|
-
import { deleteForm } from
|
|
7
|
-
import Dashboard from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { navigate, openmrsFetch, usePagination } from '@openmrs/esm-framework';
|
|
5
|
+
import { renderWithSwr, waitForLoadingToFinish } from '../../test-helpers';
|
|
6
|
+
import { deleteForm } from '../../forms.resource';
|
|
7
|
+
import Dashboard from './dashboard.component';
|
|
8
8
|
|
|
9
9
|
const mockedOpenmrsFetch = openmrsFetch as jest.Mock;
|
|
10
10
|
const mockedDeleteForm = deleteForm as jest.Mock;
|
|
11
11
|
|
|
12
|
-
jest.mock(
|
|
12
|
+
jest.mock('../../forms.resource', () => ({
|
|
13
13
|
deleteForm: jest.fn(),
|
|
14
14
|
}));
|
|
15
15
|
const mockUsePagination = usePagination as jest.Mock;
|
|
16
16
|
|
|
17
17
|
const formsResponse = [
|
|
18
18
|
{
|
|
19
|
-
uuid:
|
|
20
|
-
name:
|
|
19
|
+
uuid: '2ddde996-b1c3-37f1-a53e-378dd1a4f6b5',
|
|
20
|
+
name: 'Test Form 1',
|
|
21
21
|
encounterType: {
|
|
22
|
-
uuid:
|
|
23
|
-
name:
|
|
22
|
+
uuid: 'dd528487-82a5-4082-9c72-ed246bd49591',
|
|
23
|
+
name: 'Consultation',
|
|
24
24
|
},
|
|
25
|
-
version:
|
|
25
|
+
version: '1',
|
|
26
26
|
published: true,
|
|
27
27
|
retired: false,
|
|
28
28
|
resources: [
|
|
29
29
|
{
|
|
30
|
-
dataType:
|
|
31
|
-
name:
|
|
32
|
-
uuid:
|
|
33
|
-
valueReference:
|
|
30
|
+
dataType: 'AmpathJsonSchema',
|
|
31
|
+
name: 'JSON schema',
|
|
32
|
+
uuid: '26e45c1a-a46d-4f69-af0a-c29baaed5b3e',
|
|
33
|
+
valueReference: '9c35c3d7-1366-45ef-b4d7-ae635b22b6a7',
|
|
34
34
|
},
|
|
35
35
|
],
|
|
36
36
|
},
|
|
37
37
|
];
|
|
38
38
|
|
|
39
|
-
jest.mock(
|
|
40
|
-
const originalModule = jest.requireActual(
|
|
39
|
+
jest.mock('@openmrs/esm-framework', () => {
|
|
40
|
+
const originalModule = jest.requireActual('@openmrs/esm-framework');
|
|
41
41
|
|
|
42
42
|
return {
|
|
43
43
|
...originalModule,
|
|
@@ -50,26 +50,22 @@ jest.mock("@openmrs/esm-framework", () => {
|
|
|
50
50
|
};
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
describe(
|
|
54
|
-
it(
|
|
53
|
+
describe('Dashboard', () => {
|
|
54
|
+
it('renders an empty state view if no forms are available', async () => {
|
|
55
55
|
mockedOpenmrsFetch.mockReturnValueOnce({ data: { results: [] } });
|
|
56
56
|
|
|
57
57
|
renderDashboard();
|
|
58
58
|
|
|
59
59
|
await waitForLoadingToFinish();
|
|
60
60
|
|
|
61
|
-
expect(
|
|
62
|
-
|
|
63
|
-
).toBeInTheDocument();
|
|
64
|
-
expect(screen.getByRole("heading", { name: /forms/i })).toBeInTheDocument();
|
|
61
|
+
expect(screen.getByRole('heading', { name: /form builder/i })).toBeInTheDocument();
|
|
62
|
+
expect(screen.getByRole('heading', { name: /forms/i })).toBeInTheDocument();
|
|
65
63
|
expect(screen.getByTitle(/empty data illustration/i)).toBeInTheDocument();
|
|
66
|
-
expect(
|
|
67
|
-
screen.getByText(/there are no forms to display/i)
|
|
68
|
-
).toBeInTheDocument();
|
|
64
|
+
expect(screen.getByText(/there are no forms to display/i)).toBeInTheDocument();
|
|
69
65
|
expect(screen.getByText(/create a new form/i)).toBeInTheDocument();
|
|
70
66
|
});
|
|
71
67
|
|
|
72
|
-
it(
|
|
68
|
+
it('searches for a form by name and filters the list of forms', async () => {
|
|
73
69
|
const user = userEvent.setup();
|
|
74
70
|
|
|
75
71
|
mockedOpenmrsFetch.mockReturnValueOnce({
|
|
@@ -82,11 +78,11 @@ describe("Dashboard", () => {
|
|
|
82
78
|
|
|
83
79
|
await waitForLoadingToFinish();
|
|
84
80
|
|
|
85
|
-
const searchbox = screen.getByRole(
|
|
81
|
+
const searchbox = screen.getByRole('searchbox') as HTMLInputElement;
|
|
86
82
|
|
|
87
|
-
await waitFor(() => user.type(searchbox,
|
|
83
|
+
await waitFor(() => user.type(searchbox, 'COVID'));
|
|
88
84
|
|
|
89
|
-
expect(searchbox.value).toBe(
|
|
85
|
+
expect(searchbox.value).toBe('COVID');
|
|
90
86
|
|
|
91
87
|
mockUsePagination.mockImplementation(() => ({
|
|
92
88
|
currentPage: 1,
|
|
@@ -94,12 +90,8 @@ describe("Dashboard", () => {
|
|
|
94
90
|
results: formsResponse.filter((form) => form.name === searchbox.value),
|
|
95
91
|
}));
|
|
96
92
|
|
|
97
|
-
await waitFor(() =>
|
|
98
|
-
|
|
99
|
-
);
|
|
100
|
-
expect(
|
|
101
|
-
screen.getByText(/no matching forms to display/i)
|
|
102
|
-
).toBeInTheDocument();
|
|
93
|
+
await waitFor(() => expect(screen.queryByText(/Test Form 1/i)).not.toBeInTheDocument());
|
|
94
|
+
expect(screen.getByText(/no matching forms to display/i)).toBeInTheDocument();
|
|
103
95
|
});
|
|
104
96
|
|
|
105
97
|
it('filters the list of forms by "published" status', async () => {
|
|
@@ -115,14 +107,12 @@ describe("Dashboard", () => {
|
|
|
115
107
|
|
|
116
108
|
await waitForLoadingToFinish();
|
|
117
109
|
|
|
118
|
-
const publishStatusFilter = screen.getByRole(
|
|
110
|
+
const publishStatusFilter = screen.getByRole('combobox', {
|
|
119
111
|
name: /filter by publish status/i,
|
|
120
112
|
});
|
|
121
113
|
|
|
122
114
|
await waitFor(() => user.click(publishStatusFilter));
|
|
123
|
-
await waitFor(() =>
|
|
124
|
-
user.click(screen.getByRole("option", { name: /unpublished/i }))
|
|
125
|
-
);
|
|
115
|
+
await waitFor(() => user.click(screen.getByRole('option', { name: /unpublished/i })));
|
|
126
116
|
|
|
127
117
|
mockUsePagination.mockImplementation(() => ({
|
|
128
118
|
currentPage: 1,
|
|
@@ -131,12 +121,10 @@ describe("Dashboard", () => {
|
|
|
131
121
|
}));
|
|
132
122
|
|
|
133
123
|
expect(screen.queryByText(/Test Form 1/i)).not.toBeInTheDocument();
|
|
134
|
-
expect(
|
|
135
|
-
screen.getByText(/no matching forms to display/i)
|
|
136
|
-
).toBeInTheDocument();
|
|
124
|
+
expect(screen.getByText(/no matching forms to display/i)).toBeInTheDocument();
|
|
137
125
|
});
|
|
138
126
|
|
|
139
|
-
it(
|
|
127
|
+
it('renders a list of forms fetched from the server', async () => {
|
|
140
128
|
mockedOpenmrsFetch.mockReturnValueOnce({
|
|
141
129
|
data: {
|
|
142
130
|
results: formsResponse,
|
|
@@ -153,25 +141,13 @@ describe("Dashboard", () => {
|
|
|
153
141
|
|
|
154
142
|
await waitForLoadingToFinish();
|
|
155
143
|
|
|
156
|
-
expect(
|
|
157
|
-
|
|
158
|
-
).toBeInTheDocument();
|
|
159
|
-
expect(
|
|
160
|
-
|
|
161
|
-
).toBeInTheDocument();
|
|
162
|
-
expect(
|
|
163
|
-
screen.getByRole("button", { name: /create a new form/i })
|
|
164
|
-
).toBeInTheDocument();
|
|
165
|
-
expect(
|
|
166
|
-
screen.getByRole("button", { name: /edit schema/i })
|
|
167
|
-
).toBeInTheDocument();
|
|
168
|
-
expect(
|
|
169
|
-
screen.getByRole("button", { name: /download schema/i })
|
|
170
|
-
).toBeInTheDocument();
|
|
171
|
-
expect(
|
|
172
|
-
screen.getByRole("searchbox", { name: /filter table/i })
|
|
173
|
-
).toBeInTheDocument();
|
|
174
|
-
expect(screen.queryByRole("table")).toBeInTheDocument();
|
|
144
|
+
expect(screen.getByRole('heading', { name: /form builder/i })).toBeInTheDocument();
|
|
145
|
+
expect(screen.getByRole('combobox', { name: /filter by publish status/i })).toBeInTheDocument();
|
|
146
|
+
expect(screen.getByRole('button', { name: /create a new form/i })).toBeInTheDocument();
|
|
147
|
+
expect(screen.getByRole('button', { name: /edit schema/i })).toBeInTheDocument();
|
|
148
|
+
expect(screen.getByRole('button', { name: /download schema/i })).toBeInTheDocument();
|
|
149
|
+
expect(screen.getByRole('searchbox', { name: /filter table/i })).toBeInTheDocument();
|
|
150
|
+
expect(screen.queryByRole('table')).toBeInTheDocument();
|
|
175
151
|
expect(screen.getByText(/Test Form 1/i)).toBeInTheDocument();
|
|
176
152
|
});
|
|
177
153
|
|
|
@@ -194,7 +170,7 @@ describe("Dashboard", () => {
|
|
|
194
170
|
|
|
195
171
|
await waitForLoadingToFinish();
|
|
196
172
|
|
|
197
|
-
const createFormButton = screen.getByRole(
|
|
173
|
+
const createFormButton = screen.getByRole('button', {
|
|
198
174
|
name: /create a new form/i,
|
|
199
175
|
});
|
|
200
176
|
|
|
@@ -224,7 +200,7 @@ describe("Dashboard", () => {
|
|
|
224
200
|
|
|
225
201
|
await waitForLoadingToFinish();
|
|
226
202
|
|
|
227
|
-
const editSchemaButton = screen.getByRole(
|
|
203
|
+
const editSchemaButton = screen.getByRole('button', {
|
|
228
204
|
name: /edit schema/i,
|
|
229
205
|
});
|
|
230
206
|
|
|
@@ -253,7 +229,7 @@ describe("Dashboard", () => {
|
|
|
253
229
|
|
|
254
230
|
await waitForLoadingToFinish();
|
|
255
231
|
|
|
256
|
-
const downloadSchemaButton = screen.getByRole(
|
|
232
|
+
const downloadSchemaButton = screen.getByRole('button', {
|
|
257
233
|
name: /download schema/i,
|
|
258
234
|
});
|
|
259
235
|
|
|
@@ -282,25 +258,19 @@ describe("Dashboard", () => {
|
|
|
282
258
|
|
|
283
259
|
await waitForLoadingToFinish();
|
|
284
260
|
|
|
285
|
-
const deleteButton = screen.getByRole(
|
|
261
|
+
const deleteButton = screen.getByRole('button', { name: /delete schema/i });
|
|
286
262
|
expect(deleteButton).toBeInTheDocument();
|
|
287
263
|
|
|
288
264
|
await waitFor(() => user.click(deleteButton));
|
|
289
265
|
|
|
290
|
-
const modal = screen.getByRole(
|
|
266
|
+
const modal = screen.getByRole('presentation');
|
|
291
267
|
expect(modal).toBeInTheDocument();
|
|
292
268
|
expect(modal).toHaveTextContent(/delete form/i);
|
|
293
|
-
expect(modal).toHaveTextContent(
|
|
294
|
-
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
screen.getByRole("button", { name: /danger delete/i })
|
|
299
|
-
).toBeInTheDocument();
|
|
300
|
-
|
|
301
|
-
await waitFor(() =>
|
|
302
|
-
user.click(screen.getByRole("button", { name: /danger delete/i }))
|
|
303
|
-
);
|
|
269
|
+
expect(modal).toHaveTextContent(/are you sure you want to delete this form?/i);
|
|
270
|
+
expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();
|
|
271
|
+
expect(screen.getByRole('button', { name: /danger delete/i })).toBeInTheDocument();
|
|
272
|
+
|
|
273
|
+
await waitFor(() => user.click(screen.getByRole('button', { name: /danger delete/i })));
|
|
304
274
|
});
|
|
305
275
|
});
|
|
306
276
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
|
-
export const EmptyDataIllustration = ({ width =
|
|
3
|
+
export const EmptyDataIllustration = ({ width = '64', height = '64' }) => {
|
|
4
4
|
return (
|
|
5
5
|
<svg width={width} height={height} viewBox="0 0 64 64">
|
|
6
6
|
<title>Empty data illustration</title>
|
|
@@ -18,13 +18,7 @@ export const EmptyDataIllustration = ({ width = "64", height = "64" }) => {
|
|
|
18
18
|
fill="#C6C6C6"
|
|
19
19
|
/>
|
|
20
20
|
<circle fill="#C6C6C6" cx={17.636} cy={2.314} r={1.855} />
|
|
21
|
-
<circle
|
|
22
|
-
fill="#FFF"
|
|
23
|
-
fillRule="nonzero"
|
|
24
|
-
cx={17.636}
|
|
25
|
-
cy={2.314}
|
|
26
|
-
r={1.175}
|
|
27
|
-
/>
|
|
21
|
+
<circle fill="#FFF" fillRule="nonzero" cx={17.636} cy={2.314} r={1.175} />
|
|
28
22
|
<path
|
|
29
23
|
d="M55.893 53.995H24.544a.79.79 0 01-.788-.789V15.644a.79.79 0 01.788-.788h31.349a.79.79 0 01.788.788v37.562a.79.79 0 01-.788.789z"
|
|
30
24
|
fill="#F4F4F4"
|
|
@@ -38,13 +32,7 @@ export const EmptyDataIllustration = ({ width = "64", height = "64" }) => {
|
|
|
38
32
|
fill="#C6C6C6"
|
|
39
33
|
/>
|
|
40
34
|
<circle fill="#C6C6C6" cx={40.218} cy={9.755} r={1.855} />
|
|
41
|
-
<circle
|
|
42
|
-
fill="#FFF"
|
|
43
|
-
fillRule="nonzero"
|
|
44
|
-
cx={40.218}
|
|
45
|
-
cy={9.755}
|
|
46
|
-
r={1.13}
|
|
47
|
-
/>
|
|
35
|
+
<circle fill="#FFF" fillRule="nonzero" cx={40.218} cy={9.755} r={1.13} />
|
|
48
36
|
</g>
|
|
49
37
|
</svg>
|
|
50
38
|
);
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { Layer, Link, Tile } from
|
|
3
|
-
import { useTranslation } from
|
|
4
|
-
import { navigate, useLayoutType } from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Layer, Link, Tile } from '@carbon/react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { navigate, useLayoutType } from '@openmrs/esm-framework';
|
|
5
5
|
|
|
6
|
-
import { EmptyDataIllustration } from
|
|
7
|
-
import styles from
|
|
6
|
+
import { EmptyDataIllustration } from './empty-data-illustration.component';
|
|
7
|
+
import styles from './empty-state.scss';
|
|
8
8
|
|
|
9
9
|
function EmptyState() {
|
|
10
10
|
const { t } = useTranslation();
|
|
11
|
-
const isTablet = useLayoutType() ===
|
|
11
|
+
const isTablet = useLayoutType() === 'tablet';
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<Layer>
|
|
15
15
|
<Tile className={styles.tile}>
|
|
16
|
-
<div
|
|
17
|
-
|
|
18
|
-
>
|
|
19
|
-
<h4>{t("forms", "Forms")}</h4>
|
|
16
|
+
<div className={isTablet ? styles.tabletHeading : styles.desktopHeading}>
|
|
17
|
+
<h4>{t('forms', 'Forms')}</h4>
|
|
20
18
|
</div>
|
|
21
19
|
<EmptyDataIllustration />
|
|
22
|
-
<p className={styles.content}>
|
|
23
|
-
{t("noFormsToDisplay", "There are no forms to display.")}
|
|
24
|
-
</p>
|
|
20
|
+
<p className={styles.content}>{t('noFormsToDisplay', 'There are no forms to display.')}</p>
|
|
25
21
|
<p className={styles.action}>
|
|
26
22
|
<Link
|
|
27
23
|
onClick={() =>
|
|
@@ -30,7 +26,7 @@ function EmptyState() {
|
|
|
30
26
|
})
|
|
31
27
|
}
|
|
32
28
|
>
|
|
33
|
-
{t(
|
|
29
|
+
{t('createNewForm', 'Create a new form')}
|
|
34
30
|
</Link>
|
|
35
31
|
</p>
|
|
36
32
|
</Tile>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { Layer, Tile } from
|
|
3
|
-
import { useTranslation } from
|
|
4
|
-
import { useLayoutType } from
|
|
5
|
-
import styles from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Layer, Tile } from '@carbon/react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { useLayoutType } from '@openmrs/esm-framework';
|
|
5
|
+
import styles from './error-state.scss';
|
|
6
6
|
|
|
7
7
|
interface ErrorStateProps {
|
|
8
8
|
error: Error;
|
|
@@ -10,23 +10,21 @@ interface ErrorStateProps {
|
|
|
10
10
|
|
|
11
11
|
const ErrorState: React.FC<ErrorStateProps> = ({ error }) => {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
|
-
const isTablet = useLayoutType() ===
|
|
13
|
+
const isTablet = useLayoutType() === 'tablet';
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
16
|
<Layer>
|
|
17
17
|
<Tile className={styles.tile}>
|
|
18
|
-
<div
|
|
19
|
-
|
|
20
|
-
>
|
|
21
|
-
<h4>{t("forms", "Forms")}</h4>
|
|
18
|
+
<div className={isTablet ? styles.tabletHeading : styles.desktopHeading}>
|
|
19
|
+
<h4>{t('forms', 'Forms')}</h4>
|
|
22
20
|
</div>
|
|
23
21
|
<p className={styles.errorMessage}>
|
|
24
|
-
{t(
|
|
22
|
+
{t('error', 'Error')}: {error?.message}
|
|
25
23
|
</p>
|
|
26
24
|
<p className={styles.errorCopy}>
|
|
27
25
|
{t(
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
'errorCopy',
|
|
27
|
+
'Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.',
|
|
30
28
|
)}
|
|
31
29
|
</p>
|
|
32
30
|
</Tile>
|