@openmrs/esm-form-builder-app 2.2.2-pre.645 → 2.2.2-pre.654
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/dist/153.js +1 -1
- package/dist/153.js.map +1 -1
- package/dist/256.js +1 -1
- package/dist/319.js +1 -1
- package/dist/447.js +1 -1
- package/dist/565.js +2 -0
- package/dist/565.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/626.js +2 -0
- package/dist/626.js.map +1 -0
- package/dist/729.js +1 -0
- package/dist/729.js.map +1 -0
- package/dist/757.js +1 -1
- package/dist/788.js +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/main.js +1 -1
- package/dist/openmrs-esm-form-builder-app.js +1 -1
- package/dist/openmrs-esm-form-builder-app.js.buildmanifest.json +205 -205
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/components/dashboard/dashboard.component.tsx +28 -15
- package/src/components/dashboard/dashboard.scss +9 -10
- package/src/components/dashboard/dashboard.test.tsx +25 -3
- package/src/components/form-editor/form-editor.component.tsx +36 -14
- package/src/components/form-editor/form-editor.scss +33 -7
- package/src/components/header/header.component.tsx +43 -0
- package/src/components/header/header.scss +67 -0
- package/src/components/header/illo.component.tsx +34 -0
- package/src/index.ts +1 -19
- package/src/setup-tests.ts +3 -0
- package/dist/223.js +0 -2
- package/dist/223.js.map +0 -1
- package/dist/259.js +0 -1
- package/dist/259.js.map +0 -1
- package/dist/501.js +0 -2
- package/dist/501.js.map +0 -1
- /package/dist/{501.js.LICENSE.txt → 565.js.LICENSE.txt} +0 -0
- /package/dist/{223.js.LICENSE.txt → 626.js.LICENSE.txt} +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@use "@carbon/type";
|
|
4
4
|
|
|
5
5
|
.container {
|
|
6
|
-
padding:
|
|
6
|
+
padding: 1rem;
|
|
7
7
|
background-color: colors.$gray-10;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
.link {
|
|
53
|
+
text-decoration: none;
|
|
54
|
+
}
|
|
52
55
|
|
|
53
56
|
.table {
|
|
54
57
|
tr {
|
|
@@ -65,10 +68,6 @@
|
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
.heading {
|
|
69
|
-
margin-bottom: 1.5rem;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
71
|
.toolbar {
|
|
73
72
|
position: relative;
|
|
74
73
|
display: flex;
|
|
@@ -105,10 +104,6 @@
|
|
|
105
104
|
padding-top: 0rem;
|
|
106
105
|
}
|
|
107
106
|
|
|
108
|
-
// FIXME: This override should be moved to esm-styleguide
|
|
109
|
-
:global(.cds--btn--icon-only) {
|
|
110
|
-
padding-block-start: 0.5rem;
|
|
111
|
-
}
|
|
112
107
|
}
|
|
113
108
|
|
|
114
109
|
.filterContainer {
|
|
@@ -123,6 +118,10 @@
|
|
|
123
118
|
}
|
|
124
119
|
}
|
|
125
120
|
|
|
121
|
+
.filterDropdown {
|
|
122
|
+
margin-left: layout.$spacing-03;
|
|
123
|
+
}
|
|
124
|
+
|
|
126
125
|
.content {
|
|
127
126
|
@include type.type-style('heading-compact-02');
|
|
128
127
|
color: colors.$gray-70;
|
|
@@ -147,7 +146,7 @@
|
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
.warningMessage {
|
|
150
|
-
margin:
|
|
149
|
+
margin: 1rem 0;
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
.spinner {
|
|
@@ -8,6 +8,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
|
+
global.window.URL.createObjectURL = jest.fn();
|
|
11
12
|
|
|
12
13
|
jest.mock('../../forms.resource', () => ({
|
|
13
14
|
deleteForm: jest.fn(),
|
|
@@ -58,7 +59,7 @@ describe('Dashboard', () => {
|
|
|
58
59
|
|
|
59
60
|
await waitForLoadingToFinish();
|
|
60
61
|
|
|
61
|
-
expect(screen.
|
|
62
|
+
expect(screen.getByText(/form builder/i)).toBeInTheDocument();
|
|
62
63
|
expect(screen.getByRole('heading', { name: /forms/i })).toBeInTheDocument();
|
|
63
64
|
expect(screen.getByTitle(/empty data illustration/i)).toBeInTheDocument();
|
|
64
65
|
expect(screen.getByText(/there are no forms to display/i)).toBeInTheDocument();
|
|
@@ -141,14 +142,14 @@ describe('Dashboard', () => {
|
|
|
141
142
|
|
|
142
143
|
await waitForLoadingToFinish();
|
|
143
144
|
|
|
144
|
-
expect(screen.
|
|
145
|
+
expect(screen.getByText(/form builder/i)).toBeInTheDocument();
|
|
145
146
|
expect(screen.getByRole('combobox', { name: /filter by/i })).toBeInTheDocument();
|
|
146
147
|
expect(screen.getByRole('button', { name: /create a new form/i })).toBeInTheDocument();
|
|
147
148
|
expect(screen.getByRole('button', { name: /edit schema/i })).toBeInTheDocument();
|
|
148
149
|
expect(screen.getByRole('button', { name: /download schema/i })).toBeInTheDocument();
|
|
149
150
|
expect(screen.getByRole('searchbox', { name: /filter table/i })).toBeInTheDocument();
|
|
150
151
|
expect(screen.queryByRole('table')).toBeInTheDocument();
|
|
151
|
-
expect(screen.getByText(
|
|
152
|
+
expect(screen.getByText(formsResponse[0].name)).toBeInTheDocument();
|
|
152
153
|
});
|
|
153
154
|
|
|
154
155
|
it('clicking on "create a new form" button navigates to the "create form" page', async () => {
|
|
@@ -181,6 +182,27 @@ describe('Dashboard', () => {
|
|
|
181
182
|
});
|
|
182
183
|
});
|
|
183
184
|
|
|
185
|
+
it("clicking the form name navigates to the form's edit page", async () => {
|
|
186
|
+
mockedOpenmrsFetch.mockReturnValueOnce({
|
|
187
|
+
data: {
|
|
188
|
+
results: formsResponse,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
mockUsePagination.mockImplementation(() => ({
|
|
193
|
+
currentPage: 1,
|
|
194
|
+
goTo: () => {},
|
|
195
|
+
results: formsResponse,
|
|
196
|
+
}));
|
|
197
|
+
|
|
198
|
+
renderDashboard();
|
|
199
|
+
|
|
200
|
+
await waitForLoadingToFinish();
|
|
201
|
+
|
|
202
|
+
const link = screen.getByRole('link', { name: formsResponse[0].name });
|
|
203
|
+
expect(link).toBeInTheDocument();
|
|
204
|
+
});
|
|
205
|
+
|
|
184
206
|
it('clicking on "edit schema" button navigates to the "edit schema" page', async () => {
|
|
185
207
|
const user = userEvent.setup();
|
|
186
208
|
|
|
@@ -17,10 +17,9 @@ import {
|
|
|
17
17
|
TabPanels,
|
|
18
18
|
TabPanel,
|
|
19
19
|
} from '@carbon/react';
|
|
20
|
-
import { Download } from '@carbon/react/icons';
|
|
20
|
+
import { ArrowLeft, Download } from '@carbon/react/icons';
|
|
21
21
|
import { useParams } from 'react-router-dom';
|
|
22
22
|
import { useTranslation } from 'react-i18next';
|
|
23
|
-
import { ExtensionSlot } from '@openmrs/esm-framework';
|
|
24
23
|
import type { OHRIFormSchema } from '@openmrs/openmrs-form-engine-lib';
|
|
25
24
|
import type { Schema } from '../../types';
|
|
26
25
|
import { useClobdata } from '../../hooks/useClobdata';
|
|
@@ -28,9 +27,11 @@ import { useForm } from '../../hooks/useForm';
|
|
|
28
27
|
import ActionButtons from '../action-buttons/action-buttons.component';
|
|
29
28
|
import AuditDetails from '../audit-details/audit-details.component';
|
|
30
29
|
import FormRenderer from '../form-renderer/form-renderer.component';
|
|
30
|
+
import Header from '../header/header.component';
|
|
31
31
|
import InteractiveBuilder from '../interactive-builder/interactive-builder.component';
|
|
32
32
|
import SchemaEditor from '../schema-editor/schema-editor.component';
|
|
33
33
|
import styles from './form-editor.scss';
|
|
34
|
+
import { ConfigurableLink } from '@openmrs/esm-framework';
|
|
34
35
|
|
|
35
36
|
interface ErrorProps {
|
|
36
37
|
error: Error;
|
|
@@ -240,9 +241,8 @@ const FormEditor: React.FC = () => {
|
|
|
240
241
|
|
|
241
242
|
return (
|
|
242
243
|
<>
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
</div>
|
|
244
|
+
<Header title={t('schemaEditor', 'Schema editor')} />
|
|
245
|
+
<BackButton />
|
|
246
246
|
<div className={styles.container}>
|
|
247
247
|
{showDraftSchemaModal && <DraftSchemaModal />}
|
|
248
248
|
<Grid className={styles.grid}>
|
|
@@ -250,17 +250,21 @@ const FormEditor: React.FC = () => {
|
|
|
250
250
|
<div className={styles.actionButtons}>
|
|
251
251
|
{isLoadingFormOrSchema ? (
|
|
252
252
|
<InlineLoading description={t('loadingSchema', 'Loading schema') + '...'} />
|
|
253
|
-
) :
|
|
253
|
+
) : (
|
|
254
|
+
<h1 className={styles.formName}>{form?.name}</h1>
|
|
255
|
+
)}
|
|
254
256
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
{
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
<div>
|
|
258
|
+
{isNewSchema && !schema ? (
|
|
259
|
+
<Button kind="ghost" onClick={inputDummySchema}>
|
|
260
|
+
{t('inputDummySchema', 'Input dummy schema')}
|
|
261
|
+
</Button>
|
|
262
|
+
) : null}
|
|
260
263
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
+
<Button kind="ghost" onClick={renderSchemaChanges}>
|
|
265
|
+
<span>{t('renderChanges', 'Render changes')}</span>
|
|
266
|
+
</Button>
|
|
267
|
+
</div>
|
|
264
268
|
</div>
|
|
265
269
|
<div>
|
|
266
270
|
<div className={styles.heading}>
|
|
@@ -330,4 +334,22 @@ const FormEditor: React.FC = () => {
|
|
|
330
334
|
);
|
|
331
335
|
};
|
|
332
336
|
|
|
337
|
+
function BackButton() {
|
|
338
|
+
const { t } = useTranslation();
|
|
339
|
+
|
|
340
|
+
return (
|
|
341
|
+
<div className={styles.backButton}>
|
|
342
|
+
<ConfigurableLink to={window.getOpenmrsSpaBase() + 'form-builder'}>
|
|
343
|
+
<Button
|
|
344
|
+
kind="ghost"
|
|
345
|
+
renderIcon={(props) => <ArrowLeft size={24} {...props} />}
|
|
346
|
+
iconDescription="Return to dashboard"
|
|
347
|
+
>
|
|
348
|
+
<span>{t('backToDashboard', 'Back to dashboard')}</span>
|
|
349
|
+
</Button>
|
|
350
|
+
</ConfigurableLink>
|
|
351
|
+
</div>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
333
355
|
export default FormEditor;
|
|
@@ -8,12 +8,6 @@
|
|
|
8
8
|
flex-direction: column;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
.breadcrumbsContainer {
|
|
12
|
-
nav {
|
|
13
|
-
background-color: colors.$white-0;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
11
|
.grid {
|
|
18
12
|
margin-left: 0;
|
|
19
13
|
margin-right: 0;
|
|
@@ -41,7 +35,7 @@
|
|
|
41
35
|
.actionButtons {
|
|
42
36
|
display: flex;
|
|
43
37
|
align-items: center;
|
|
44
|
-
justify-content:
|
|
38
|
+
justify-content: space-between;
|
|
45
39
|
margin: 1rem 0;
|
|
46
40
|
|
|
47
41
|
button {
|
|
@@ -49,6 +43,10 @@
|
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
45
|
|
|
46
|
+
.formName {
|
|
47
|
+
@include type.type-style('heading-03');
|
|
48
|
+
}
|
|
49
|
+
|
|
52
50
|
.editorContainer {
|
|
53
51
|
padding: 1rem;
|
|
54
52
|
}
|
|
@@ -67,3 +65,31 @@
|
|
|
67
65
|
width: 100%;
|
|
68
66
|
padding: 0.75rem;
|
|
69
67
|
}
|
|
68
|
+
|
|
69
|
+
.backButton {
|
|
70
|
+
margin-left: layout.$spacing-05;
|
|
71
|
+
padding: layout.$spacing-03 0;
|
|
72
|
+
max-width: fit-content;
|
|
73
|
+
|
|
74
|
+
a {
|
|
75
|
+
text-decoration: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
button {
|
|
79
|
+
display: flex;
|
|
80
|
+
padding-left: 0 !important;
|
|
81
|
+
|
|
82
|
+
svg {
|
|
83
|
+
order: 1;
|
|
84
|
+
margin: 0 layout.$spacing-03;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
span {
|
|
88
|
+
order: 2;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
button {
|
|
94
|
+
padding-block-start: 0.5rem;
|
|
95
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Calendar, Location, UserFollow } from '@carbon/react/icons';
|
|
4
|
+
import { formatDate, useSession } from '@openmrs/esm-framework';
|
|
5
|
+
import Illustration from './illo.component';
|
|
6
|
+
import styles from './header.scss';
|
|
7
|
+
|
|
8
|
+
interface HeaderProps {
|
|
9
|
+
title: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Header: React.FC<HeaderProps> = ({ title }) => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const session = useSession();
|
|
15
|
+
const location = session?.sessionLocation?.display;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className={styles.header}>
|
|
19
|
+
<div className={styles['left-justified-items']}>
|
|
20
|
+
<Illustration />
|
|
21
|
+
<div className={styles['page-labels']}>
|
|
22
|
+
<p>{t('formBuilder', 'Form builder')}</p>
|
|
23
|
+
<p className={styles['page-name']}>{title}</p>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div className={styles['right-justified-items']}>
|
|
27
|
+
<div className={styles.userContainer}>
|
|
28
|
+
<p>{session?.user?.person?.display}</p>
|
|
29
|
+
<UserFollow size={16} className={styles.userIcon} />
|
|
30
|
+
</div>
|
|
31
|
+
<div className={styles['date-and-location']}>
|
|
32
|
+
<Location size={16} />
|
|
33
|
+
<span className={styles.value}>{location}</span>
|
|
34
|
+
<span className={styles.middot}>·</span>
|
|
35
|
+
<Calendar size={16} />
|
|
36
|
+
<span className={styles.value}>{formatDate(new Date(), { mode: 'standard' })}</span>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default Header;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@carbon/type';
|
|
3
|
+
@import '~@openmrs/esm-styleguide/src/vars';
|
|
4
|
+
|
|
5
|
+
.header {
|
|
6
|
+
@include type.type-style('body-compact-02');
|
|
7
|
+
color: $text-02;
|
|
8
|
+
height: layout.$spacing-12;
|
|
9
|
+
background-color: $ui-02;
|
|
10
|
+
border-bottom: 1px solid $ui-03;
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: space-between;
|
|
13
|
+
padding: layout.$spacing-05;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.left-justified-items {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
align-items: center;
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.right-justified-items {
|
|
25
|
+
@include type.type-style('body-compact-02');
|
|
26
|
+
color: $text-02;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.page-name {
|
|
33
|
+
@include type.type-style('heading-04');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.page-labels {
|
|
37
|
+
margin: layout.$spacing-03;
|
|
38
|
+
|
|
39
|
+
p:first-of-type {
|
|
40
|
+
margin-bottom: layout.$spacing-02;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.date-and-location {
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: flex-end;
|
|
47
|
+
align-items: center;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.userContainer {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: flex-end;
|
|
54
|
+
gap: layout.$spacing-05;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.value {
|
|
58
|
+
margin-left: layout.$spacing-02;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.middot {
|
|
62
|
+
margin: 0 layout.$spacing-03;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.view {
|
|
66
|
+
@include type.type-style('label-01');
|
|
67
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const Illustration: React.FC = () => {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
height="64"
|
|
7
|
+
width="64"
|
|
8
|
+
viewBox="0 0 32 32"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
xmlSpace="preserve"
|
|
11
|
+
fill-rule="evenodd"
|
|
12
|
+
clipRule="evenodd"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
strokeMiterlimit="2"
|
|
15
|
+
>
|
|
16
|
+
<path
|
|
17
|
+
d="M27 31.36H8a.36.36 0 0 1-.36-.36v-1.64H6a.36.36 0 0 1-.36-.36v-1.64H5a.36.36 0 0 1-.36-.36V3A.36.36 0 0 1 5 2.64h4.64V2a.36.36 0 0 1 .36-.36h1.64V1A.36.36 0 0 1 12 .64h4a.36.36 0 0 1 .36.36v.64H18a.36.36 0 0 1 .36.36v.64H23a.36.36 0 0 1 .36.36v1.64H25a.36.36 0 0 1 .36.36v1.64H27a.36.36 0 0 1 .36.36v24a.36.36 0 0 1-.36.36Z"
|
|
18
|
+
fill="#d2e5e5"
|
|
19
|
+
/>
|
|
20
|
+
<path d="M8.36 30.64h18.28V7.36h-1.28V29a.36.36 0 0 1-.36.36H8.36v1.28Z" fill="#8abab8" />
|
|
21
|
+
<path
|
|
22
|
+
d="M5.36 26.64h17.28V3.36h-4.28V4a.36.36 0 0 1-.36.36h-8A.36.36 0 0 1 9.64 4v-.64H5.36v23.28Z"
|
|
23
|
+
fill="#8abab8"
|
|
24
|
+
/>
|
|
25
|
+
<path fill="#fff" d="M7.5 12.64h13v.72h-13zM7.5 8.64h13v.72h-13zM7.5 20.64h13v.72h-13zM7.5 16.64h13v.72h-13z" />
|
|
26
|
+
<path
|
|
27
|
+
d="M10.36 3.64h7.28V2.36H16a.36.36 0 0 1-.36-.36v-.64h-3.28V2a.36.36 0 0 1-.36.36h-1.64v1.28ZM6.36 28.64h18.28V5.36h-1.28V27a.36.36 0 0 1-.36.36H6.36v1.28Z"
|
|
28
|
+
fill="#8abab8"
|
|
29
|
+
/>
|
|
30
|
+
</svg>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default Illustration;
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConfigSchema, getAsyncLifecycle
|
|
1
|
+
import { defineConfigSchema, getAsyncLifecycle } from '@openmrs/esm-framework';
|
|
2
2
|
import { configSchema } from './config-schema';
|
|
3
3
|
|
|
4
4
|
const moduleName = '@openmrs/esm-form-builder-app';
|
|
@@ -19,22 +19,4 @@ export const systemAdministrationFormBuilderCardLink = getAsyncLifecycle(
|
|
|
19
19
|
|
|
20
20
|
export function startupApp() {
|
|
21
21
|
defineConfigSchema(moduleName, configSchema);
|
|
22
|
-
|
|
23
|
-
registerBreadcrumbs([
|
|
24
|
-
{
|
|
25
|
-
path: `${window.spaBase}/form-builder`,
|
|
26
|
-
title: 'Form Builder',
|
|
27
|
-
parent: `${window.spaBase}/home`,
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
path: `${window.spaBase}/form-builder/new`,
|
|
31
|
-
title: 'Form Editor',
|
|
32
|
-
parent: `${window.spaBase}/form-builder`,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
path: `${window.spaBase}/form-builder/edit/:uuid`,
|
|
36
|
-
title: 'Form Editor',
|
|
37
|
-
parent: `${window.spaBase}/form-builder`,
|
|
38
|
-
},
|
|
39
|
-
]);
|
|
40
22
|
}
|