@tsed/react-formio 1.11.2 → 1.12.0

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.
Files changed (141) hide show
  1. package/.env +2 -1
  2. package/craco.config.js +11 -1
  3. package/dist/components/alert/alert.component.spec.d.ts +1 -0
  4. package/dist/components/alert/alert.stories.d.ts +15 -0
  5. package/dist/components/form-action/formAction.stories.d.ts +90 -414
  6. package/dist/components/input-text/inputText.component.d.ts +1 -1
  7. package/dist/components/input-text/inputText.component.spec.d.ts +1 -0
  8. package/dist/components/select/select.component.spec.d.ts +1 -0
  9. package/dist/components/tabs/tabs.component.spec.d.ts +1 -0
  10. package/dist/index.js +60 -30
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.modern.js +59 -31
  13. package/dist/index.modern.js.map +1 -1
  14. package/jest.config.js +1 -1
  15. package/package.json +5 -9
  16. package/readme.md +74 -79
  17. package/src/components/__fixtures__/form-schema.json +10 -42
  18. package/src/components/__fixtures__/form.fixture.json +1 -1
  19. package/src/components/actions-table/actionsTable.component.spec.tsx +4 -13
  20. package/src/components/actions-table/actionsTable.component.tsx +3 -11
  21. package/src/components/alert/alert.component.spec.tsx +97 -0
  22. package/src/components/alert/alert.component.tsx +2 -8
  23. package/src/components/alert/alert.stories.tsx +17 -0
  24. package/src/components/card/card.component.tsx +1 -5
  25. package/src/components/form/form.component.tsx +1 -7
  26. package/src/components/form/useForm.hook.ts +4 -13
  27. package/src/components/form-access/formAccess.component.tsx +19 -82
  28. package/src/components/form-access/formAccess.schema.ts +7 -23
  29. package/src/components/form-access/formAccess.stories.tsx +2 -9
  30. package/src/components/form-access/formAccess.utils.spec.ts +4 -22
  31. package/src/components/form-access/formAccess.utils.ts +7 -29
  32. package/src/components/form-action/formAction.component.tsx +3 -19
  33. package/src/components/form-action/formAction.stories.tsx +251 -672
  34. package/src/components/form-builder/formBuilder.component.tsx +4 -13
  35. package/src/components/form-builder/formBuilder.stories.tsx +12 -24
  36. package/src/components/form-control/formControl.component.tsx +2 -8
  37. package/src/components/form-edit/formCtas.component.tsx +5 -23
  38. package/src/components/form-edit/formEdit.component.tsx +2 -20
  39. package/src/components/form-edit/formEdit.reducer.ts +2 -8
  40. package/src/components/form-edit/formEdit.stories.tsx +3 -15
  41. package/src/components/form-edit/formParameters.component.tsx +3 -20
  42. package/src/components/form-edit/useFormEdit.hook.ts +2 -9
  43. package/src/components/form-settings/formSettings.component.spec.tsx +2 -9
  44. package/src/components/form-settings/formSettings.component.tsx +6 -34
  45. package/src/components/form-settings/formSettings.stories.tsx +1 -6
  46. package/src/components/form-settings/formSettings.utils.spec.ts +1 -4
  47. package/src/components/form-settings/formSettings.utils.ts +2 -7
  48. package/src/components/forms-table/components/formCell.component.tsx +2 -6
  49. package/src/components/forms-table/formsTable.component.tsx +2 -7
  50. package/src/components/input-tags/inputTags.component.tsx +10 -34
  51. package/src/components/input-tags/inputTags.stories.tsx +4 -14
  52. package/src/components/input-text/inputText.component.spec.tsx +56 -0
  53. package/src/components/input-text/inputText.component.tsx +4 -5
  54. package/src/components/input-text/inputText.stories.tsx +6 -26
  55. package/src/components/loader/loader.component.tsx +2 -11
  56. package/src/components/modal/modal.component.spec.tsx +8 -14
  57. package/src/components/modal/modal.component.tsx +6 -27
  58. package/src/components/modal/modal.stories.tsx +1 -5
  59. package/src/components/modal/removeModal.component.tsx +4 -22
  60. package/src/components/pagination/pagination.component.spec.tsx +12 -38
  61. package/src/components/pagination/pagination.component.tsx +8 -41
  62. package/src/components/pagination/pagination.stories.tsx +1 -5
  63. package/src/components/react-component/reactComponent.component.tsx +3 -11
  64. package/src/components/select/select.component.spec.tsx +86 -0
  65. package/src/components/select/select.component.tsx +11 -15
  66. package/src/components/select/select.stories.tsx +6 -26
  67. package/src/components/submissions-table/submissionsTable.component.tsx +1 -3
  68. package/src/components/submissions-table/submissionsTable.stories.tsx +1 -1
  69. package/src/components/table/components/defaultArrowSort.component.tsx +1 -10
  70. package/src/components/table/components/defaultCell.component.tsx +1 -4
  71. package/src/components/table/components/defaultCellHeader.component.tsx +4 -14
  72. package/src/components/table/components/defaultCellOperations.component.tsx +14 -25
  73. package/src/components/table/components/defaultOperationButton.component.tsx +2 -10
  74. package/src/components/table/filters/defaultColumnFilter.component.spec.tsx +1 -1
  75. package/src/components/table/filters/selectColumnFilter.component.spec.tsx +2 -10
  76. package/src/components/table/filters/selectColumnFilter.component.tsx +2 -6
  77. package/src/components/table/table.component.tsx +13 -53
  78. package/src/components/table/table.stories.tsx +1 -1
  79. package/src/components/table/utils/getPageNumbers.ts +3 -11
  80. package/src/components/table/utils/mapFormToColumns.tsx +14 -22
  81. package/src/components/table/utils/useOperations.hook.tsx +2 -12
  82. package/src/components/tabs/tabs.component.spec.tsx +86 -0
  83. package/src/components/tabs/tabs.component.stories.tsx +2 -9
  84. package/src/components/tabs/tabs.component.tsx +9 -43
  85. package/src/interfaces/Operation.ts +1 -4
  86. package/src/react-table.d.ts +9 -28
  87. package/src/stores/action/action.actions.ts +31 -33
  88. package/src/stores/action/action.reducers.spec.ts +1 -8
  89. package/src/stores/action/action.reducers.ts +1 -8
  90. package/src/stores/action/action.selectors.ts +1 -2
  91. package/src/stores/action-info/action-info.actions.spec.ts +1 -5
  92. package/src/stores/action-info/action-info.actions.ts +16 -19
  93. package/src/stores/action-info/action-info.reducers.spec.ts +1 -6
  94. package/src/stores/action-info/action-info.reducers.ts +1 -6
  95. package/src/stores/action-info/action-info.selectors.ts +1 -4
  96. package/src/stores/actions/actions.actions.spec.ts +1 -6
  97. package/src/stores/actions/actions.actions.ts +16 -19
  98. package/src/stores/actions/actions.reducers.spec.ts +1 -6
  99. package/src/stores/actions/actions.reducers.ts +1 -6
  100. package/src/stores/actions/actions.selectors.ts +2 -4
  101. package/src/stores/auth/auth.reducers.ts +1 -4
  102. package/src/stores/auth/auth.selectors.spec.ts +1 -5
  103. package/src/stores/auth/auth.selectors.ts +3 -6
  104. package/src/stores/auth/auth.utils.tsx +2 -8
  105. package/src/stores/auth/getAccess.action.spec.ts +11 -54
  106. package/src/stores/auth/getAccess.action.ts +1 -6
  107. package/src/stores/auth/initAuth.action.ts +15 -17
  108. package/src/stores/form/form.actions.spec.ts +8 -39
  109. package/src/stores/form/form.actions.ts +55 -64
  110. package/src/stores/form/form.reducers.spec.ts +1 -7
  111. package/src/stores/form/form.reducers.ts +1 -8
  112. package/src/stores/form/form.selectors.ts +1 -2
  113. package/src/stores/forms/forms.actions.spec.ts +5 -18
  114. package/src/stores/forms/forms.actions.ts +17 -21
  115. package/src/stores/forms/forms.reducers.spec.ts +1 -6
  116. package/src/stores/forms/forms.reducers.ts +2 -13
  117. package/src/stores/forms/forms.selectors.ts +2 -4
  118. package/src/stores/index.spec.ts +6 -9
  119. package/src/stores/root/root.selectors.spec.ts +1 -6
  120. package/src/stores/root/root.selectors.ts +6 -24
  121. package/src/stores/submission/submission.actions.spec.ts +11 -33
  122. package/src/stores/submission/submission.actions.ts +57 -66
  123. package/src/stores/submission/submission.reducers.spec.ts +17 -27
  124. package/src/stores/submission/submission.reducers.ts +1 -4
  125. package/src/stores/submission/submission.selectors.ts +1 -4
  126. package/src/stores/submissions/submissions.actions.spec.ts +5 -18
  127. package/src/stores/submissions/submissions.actions.ts +17 -26
  128. package/src/stores/submissions/submissions.reducers.spec.ts +3 -12
  129. package/src/stores/submissions/submissions.reducers.ts +3 -17
  130. package/src/stores/submissions/submissions.selectors.spec.ts +1 -4
  131. package/src/stores/submissions/submissions.selectors.ts +2 -4
  132. package/src/utils/getEventValue.ts +1 -4
  133. package/src/utils/iconClass.ts +2 -10
  134. package/src/utils/mapPagination.ts +1 -6
  135. package/src/utils/mapRequestParams.ts +2 -12
  136. package/src/utils/url.test.ts +4 -12
  137. package/src/utils/url.ts +2 -7
  138. package/tsconfig.json +4 -12
  139. package/tsconfig.test.json +1 -1
  140. package/.eslintrc +0 -47
  141. package/.prettierrc +0 -10
package/jest.config.js CHANGED
@@ -1 +1 @@
1
- module.exports = require("@tsed/config/jest.config");
1
+ module.exports = require("@tsed/config/jest.config")("react-formio");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsed/react-formio",
3
- "version": "1.11.2",
3
+ "version": "1.12.0",
4
4
  "description": "Provide a react formio wrapper. Written in TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.modern.js",
@@ -8,13 +8,10 @@
8
8
  "scripts": {
9
9
  "test": "cross-env CI=1 yarn craco test --coverage",
10
10
  "build": "microbundle --no-compress --format modern,cjs --jsx React.createElement",
11
- "watch": "microbundle watch --no-compress --format modern,cjs --jsx React.createElement",
12
- "lint:fix": "yarn lint --fix",
13
- "lint": "yarn eslint --config .eslintrc --cache --quiet \"./src/**/*.{ts,tsx}\"",
14
- "prettier": "prettier '{src,test}/**/*.{ts,tsx}' --write"
11
+ "watch": "microbundle watch --no-compress --format modern,cjs --jsx React.createElement"
15
12
  },
16
13
  "dependencies": {
17
- "@tsed/redux-utils": "1.11.2",
14
+ "@tsed/redux-utils": "1.12.0",
18
15
  "eventemitter2": "^6.4.3",
19
16
  "prop-types": "^15.7.2"
20
17
  },
@@ -29,9 +26,8 @@
29
26
  "tooltip.js": ">=1.3.3"
30
27
  },
31
28
  "devDependencies": {
32
- "@tsed/tailwind": "1.11.2",
33
- "@tsed/tailwind-formio": "1.11.2",
34
- "eslint-plugin-jsx-a11y": "^6.5.1"
29
+ "@tsed/tailwind": "1.12.0",
30
+ "@tsed/tailwind-formio": "1.12.0"
35
31
  },
36
32
  "repository": "https://github.com/TypedProject/tsed-formio",
37
33
  "bugs": {
package/readme.md CHANGED
@@ -33,23 +33,23 @@ See our [storybook](https://formio.tsed.io/) to see all available components.
33
33
 
34
34
  ## Features
35
35
 
36
- * Many components are provided to build your own backoffice based on Formio.js API:
37
- * [ActionsTable](https://formio.tsed.io/?path=/story/reactformio-actionstable--sandbox),
38
- * [FormAccess](https://formio.tsed.io/?path=/story/reactformio-formaccess--sandbox),
39
- * [FormAction](https://formio.tsed.io/?path=/story/reactformio-formaction--sandbox),
40
- * [Form](https://formio.tsed.io/?path=/story/reactformio-form--sandbox),
41
- * [FormBuilder](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox),
42
- * [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox),
43
- * [FormsTable](https://formio.tsed.io/?path=/story/reactformio-formstable--sandbox),
44
- * [InputTags](https://formio.tsed.io/?path=/story/reactformio-inputtags--sandbox),
45
- * [InputText](https://formio.tsed.io/?path=/story/reactformio-inputtext--sandbox),
46
- * [Pagination](https://formio.tsed.io/?path=/story/reactformio-pagination--sandbox),
47
- * [Select](https://formio.tsed.io/?path=/story/reactformio-select--sandbox),
48
- * [SubmissionsTable](https://formio.tsed.io/?path=/story/reactformio-subssionsstable--sandbox).
49
- * [Table](https://formio.tsed.io/?path=/story/reactformio-table--sandbox),
50
- * Predefined Reducers for Actions, Action, Form, Forms, Submission, Submissions, etc...,
51
- * TypeScript support.
52
- * Tailwind support.
36
+ - Many components are provided to build your own backoffice based on Formio.js API:
37
+ - [ActionsTable](https://formio.tsed.io/?path=/story/reactformio-actionstable--sandbox),
38
+ - [FormAccess](https://formio.tsed.io/?path=/story/reactformio-formaccess--sandbox),
39
+ - [FormAction](https://formio.tsed.io/?path=/story/reactformio-formaction--sandbox),
40
+ - [Form](https://formio.tsed.io/?path=/story/reactformio-form--sandbox),
41
+ - [FormBuilder](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox),
42
+ - [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox),
43
+ - [FormsTable](https://formio.tsed.io/?path=/story/reactformio-formstable--sandbox),
44
+ - [InputTags](https://formio.tsed.io/?path=/story/reactformio-inputtags--sandbox),
45
+ - [InputText](https://formio.tsed.io/?path=/story/reactformio-inputtext--sandbox),
46
+ - [Pagination](https://formio.tsed.io/?path=/story/reactformio-pagination--sandbox),
47
+ - [Select](https://formio.tsed.io/?path=/story/reactformio-select--sandbox),
48
+ - [SubmissionsTable](https://formio.tsed.io/?path=/story/reactformio-subssionsstable--sandbox).
49
+ - [Table](https://formio.tsed.io/?path=/story/reactformio-table--sandbox),
50
+ - Predefined Reducers for Actions, Action, Form, Forms, Submission, Submissions, etc...,
51
+ - TypeScript support.
52
+ - Tailwind support.
53
53
 
54
54
  ## Install
55
55
 
@@ -66,30 +66,29 @@ npm install formiojs choices.js --save // Install formiojs since it is a peerDep
66
66
 
67
67
  ```tsx
68
68
  import React from "react";
69
- import {FormBuilder} from "@tsed/react-formio";
69
+ import { FormBuilder } from "@tsed/react-formio";
70
70
 
71
71
  function App() {
72
72
  return (
73
- <div className="App">
74
- <FormBuilder display={'form'} components={[]} />
73
+ <div className='App'>
74
+ <FormBuilder display={"form"} components={[]} />
75
75
  </div>
76
76
  );
77
77
  }
78
78
 
79
79
  export default App;
80
-
81
80
  ```
82
81
 
83
82
  ## Components
84
83
 
85
84
  ### Form
86
85
 
87
- The form component is the primary component of the system. It is what takes the form definition (json) and renders the form into html. There are multiple ways to send the form to the Form component. The two main ways are to pass the ```src``` prop with a url to the form definition, usually a form.io server. The other is to pass the ```form``` prop with the json definition and optionally a ```url``` prop with the location of the form.
86
+ The form component is the primary component of the system. It is what takes the form definition (json) and renders the form into html. There are multiple ways to send the form to the Form component. The two main ways are to pass the `src` prop with a url to the form definition, usually a form.io server. The other is to pass the `form` prop with the json definition and optionally a `url` prop with the location of the form.
88
87
 
89
88
  #### Props
90
89
 
91
90
  | Name | Type | Default | Description |
92
- |--------------|--------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
91
+ | ------------ | ------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
93
92
  | `src` | url | | The url of the form definition. This is commonly from a form.io server. When using src, the form will automatically submit the data to that url as well. |
94
93
  | `url` | url | | The url of the form definition. The form will not be loaded from this url and the submission will not be saved here either. This is used for file upload, oauth and other components or actions that need to know where the server is. Use this in connection with `form` |
95
94
  | `form` | object | | Instead of loading a form from the `src` url, you can preload the form definition and pass it in with the `form` prop. You should also set `url` if you are using any advanced components like file upload or oauth. |
@@ -101,13 +100,13 @@ The form component is the primary component of the system. It is what takes the
101
100
  You can respond to various events in the form. Simply pass in a prop with a function for one of these events.
102
101
 
103
102
  | Name | Parameters | Description |
104
- |-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
103
+ | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
105
104
  | `onSubmit` | `submission`: object | When the submit button is pressed and the submission has started. If `src` is not provided, this will be the final submit event. |
106
105
  | `onSubmitDone` | `submission`: object | When the submission has successfully been made to the server. This will only fire if `src` is set. |
107
106
  | `onChange` | `submission`: object, `submission.changed`: object of what changed, `submission.isValid`: boolean - if the submission passes validations. | A value in the submission has changed. |
108
107
  | `onError` | `errors`: array or string or boolean | Called when an error occurs during submission such as a validation issue. |
109
108
  | `onRender` | | Triggers when the form is finished rendering. |
110
- | `onCustomEvent` | { `type`: string - event type, `component`: object - triggering component, `data`: object - data for component, `event`: string - raw event } | Event that is triggered from a button configured with "Event" type. |
109
+ | `onCustomEvent` | { `type`: string - event type, `component`: object - triggering component, `data`: object - data for component, `event`: string - raw event } | Event that is triggered from a button configured with "Event" type. |
111
110
  | `onPrevPage` | { `page`: integer - new page number, `submission`: object - submission data } | Triggered for wizards when "Previous" button is pressed |
112
111
  | `onNextPage` | { `page`: integer - new page number, `submission`: object - submission data } | Triggered for wizards when "Next" button is pressed |
113
112
  | `onFormReady` | `formInstance`: Webform/Wizard - form class instance | Called when the form gets ready state |
@@ -119,14 +118,11 @@ You can respond to various events in the form. Simply pass in a prop with a func
119
118
  Give `Form` a `src` property and render:
120
119
 
121
120
  ```tsx
122
- import React from 'react';
123
- import ReactDOM from 'react-dom';
124
- import {Form} from '@tsed/react-formio';
121
+ import React from "react";
122
+ import ReactDOM from "react-dom";
123
+ import { Form } from "@tsed/react-formio";
125
124
 
126
- ReactDOM.render(
127
- <Form src="https://example.form.io/example" onSubmit={console.log} />
128
- , document.getElementById('example')
129
- );
125
+ ReactDOM.render(<Form src='https://example.form.io/example' onSubmit={console.log} />, document.getElementById("example"));
130
126
  ```
131
127
 
132
128
  ##### With form
@@ -134,53 +130,56 @@ ReactDOM.render(
134
130
  Give `Form` a `src` property and render:
135
131
 
136
132
  ```tsx
137
- import React from 'react';
138
- import ReactDOM from 'react-dom';
139
- import {Form} from '@tsed/react-formio';
140
-
133
+ import React from "react";
134
+ import ReactDOM from "react-dom";
135
+ import { Form } from "@tsed/react-formio";
136
+
141
137
  interface MyFormData {
142
138
  title: string;
143
- }
139
+ }
144
140
 
145
141
  const form = {
146
- display: 'form',
142
+ display: "form",
147
143
  components: [
148
144
  {
149
- key: 'title',
150
- type: 'textfield'
145
+ key: "title",
146
+ type: "textfield"
151
147
  }
152
148
  ]
153
- }
149
+ };
154
150
 
155
151
  ReactDOM.render(
156
- <Form<MyFormData> form={form} onSubmit={(submission) => {
157
- console.log(submission)
158
- }} />
159
- , document.getElementById('example')
152
+ <Form<MyFormData>
153
+ form={form}
154
+ onSubmit={(submission) => {
155
+ console.log(submission);
156
+ }}
157
+ />,
158
+ document.getElementById("example")
160
159
  );
161
160
  ```
162
161
 
163
162
  ### FormBuilder
164
163
 
165
- The [FormBuilder]([FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)) class can be used
166
- to embed a form builder directly in your react application.
164
+ The [FormBuilder](<[FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)>) class can be used
165
+ to embed a form builder directly in your react application.
167
166
  Please note that you'll need to include the CSS for the form builder from formio.js as well.
168
167
 
169
- Please note that the [FormBuilder]([FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)) component
170
- does not load and save from/to a url. You must handle the form definition loading and saving yourself or use
168
+ Please note that the [FormBuilder](<[FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)>) component
169
+ does not load and save from/to a url. You must handle the form definition loading and saving yourself or use
171
170
  the [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox) component.
172
171
 
173
172
  #### Props
174
173
 
175
174
  | Name | Type | Default | Description |
176
- |-----------|--------|---------|----------------------------------------------------------------------------------------------------------------------------------------------|
175
+ | --------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
177
176
  | `form` | object | | This is the form definition object. It should at least have a `display` property set to form, wizard or pdf. |
178
177
  | `options` | object | | an options object that can pass options to the formio.js Form that is rendered. There are many options to be found in the formio.js library. |
179
178
 
180
179
  #### Event Props
181
180
 
182
181
  | Name | Parameters | Description |
183
- |---------------------|---------------------|------------------------------------------------------------------|
182
+ | ------------------- | ------------------- | ---------------------------------------------------------------- |
184
183
  | `onChange` | `schema`: object | Triggered any time the form definition changes |
185
184
  | `onEditComponent` | `component`: object | Triggered when the component settings dialog is opened |
186
185
  | `onSaveComponent` | `component`: object | Triggered when the component settings dialog is saved and closed |
@@ -191,33 +190,30 @@ the [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox
191
190
  #### Example
192
191
 
193
192
  ```tsx
194
- import React from 'react';
195
- import ReactDOM from 'react-dom';
196
- import {FormBuilder} from '@tsed/react-formio';
193
+ import React from "react";
194
+ import ReactDOM from "react-dom";
195
+ import { FormBuilder } from "@tsed/react-formio";
197
196
 
198
- ReactDOM.render(
199
- <FormBuilder form={{display: 'form'}} onChange={(schema) => console.log(schema)} />
200
- , document.getElementById('builder')
201
- );
197
+ ReactDOM.render(<FormBuilder form={{ display: "form" }} onChange={(schema) => console.log(schema)} />, document.getElementById("builder"));
202
198
  ```
203
199
 
204
200
  ### FormEdit
205
201
 
206
- The [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox) component wraps
207
- the [FormBuilder]([FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)) component and adds the title, display, name and path fields at the top along with a save button.
202
+ The [FormEdit](https://formio.tsed.io/?path=/story/reactformio-formedit--sandbox) component wraps
203
+ the [FormBuilder](<[FormsTable](https://formio.tsed.io/?path=/story/reactformio-formbuilder--sandbox)>) component and adds the title, display, name and path fields at the top along with a save button.
208
204
 
209
205
  #### Props
210
206
 
211
- | Name | Type | Default | Description |
212
- |------------|--------|--------------------|------------------------------------------------------|
213
- | `form` | object | {display: 'form' \ | 'wizard'} | The form definition of the exiting form that is to be modified. |
214
- | `options` | object | {} | The options to be passed to FormBuilder |
215
- | `saveText` | string | '' | The string that will be displayed in the save-button |
207
+ | Name | Type | Default | Description |
208
+ | ---------- | ------ | ------------------- | ---------------------------------------------------- | --------------------------------------------------------------- |
209
+ | `form` | object | {display: 'form' \ | 'wizard'} | The form definition of the exiting form that is to be modified. |
210
+ | `options` | object | {} | The options to be passed to FormBuilder |
211
+ | `saveText` | string | '' | The string that will be displayed in the save-button |
216
212
 
217
213
  #### Event Props
218
214
 
219
215
  | Name | Parameters | Description |
220
- |------------|------------|----------------------------------------------------------------------------------------|
216
+ | ---------- | ---------- | -------------------------------------------------------------------------------------- |
221
217
  | `onSubmit` | form | Called when the save button is pressed. Will pass the form definition to the callback. |
222
218
 
223
219
  ### FormsTable
@@ -227,7 +223,7 @@ The [FormsTable](https://formio.tsed.io/?path=/story/reactformio-formstable--san
227
223
  #### Props
228
224
 
229
225
  | Name | Type | Default | Description |
230
- |--------|----------------|---------|---------------------------------------------|
226
+ | ------ | -------------- | ------- | ------------------------------------------- |
231
227
  | `data` | array of forms | [] | A list of forms to be rendered in the grid. |
232
228
 
233
229
  ### SubmissionsTable
@@ -237,7 +233,7 @@ The submisison grid will render a list of submissions and allow clicking on one
237
233
  #### Props
238
234
 
239
235
  | Name | Type | Default | Description |
240
- |--------|----------------------|---------|----------------------------------------------------------------------------------|
236
+ | ------ | -------------------- | ------- | -------------------------------------------------------------------------------- |
241
237
  | `data` | array of submissions | [] | A list of submissions to be rendered in the grid. |
242
238
  | `form` | object | {} | The form definition for the submissions. This is used to render the submissions. |
243
239
 
@@ -287,30 +283,29 @@ import { connectRouter } from "connected-react-router";
287
283
  import { combineReducers } from "redux";
288
284
 
289
285
  export const rootReducers = (history: any) =>
290
- combineReducers({
291
- router: connectRouter(history),
292
- ...defaultFormioReducer,
293
- // override defaultFormioReducer can done as following
294
- ...combine(
295
- formsReducer("forms", { query: { type: "form", tags: ['common'] } }), // return only forms with the common tags
296
- formsReducer("resources", { query: { type: "resource", tags: ['common'] } }) // return only resources with the common tags
297
- )
298
- });
286
+ combineReducers({
287
+ router: connectRouter(history),
288
+ ...defaultFormioReducer,
289
+ // override defaultFormioReducer can done as following
290
+ ...combine(
291
+ formsReducer("forms", { query: { type: "form", tags: ["common"] } }), // return only forms with the common tags
292
+ formsReducer("resources", { query: { type: "resource", tags: ["common"] } }) // return only resources with the common tags
293
+ )
294
+ });
299
295
  ```
300
296
 
301
297
  ## Contributors
298
+
302
299
  Please read [contributing guidelines here](./CONTRIBUTING.md).
303
300
 
304
301
  <a href="https://github.com/TypedProject/tsed/graphs/contributors"><img src="https://opencollective.com/tsed/contributors.svg?width=890" /></a>
305
302
 
306
-
307
303
  ## Backers
308
304
 
309
305
  Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/tsed#backer)]
310
306
 
311
307
  <a href="https://opencollective.com/tsed#backers" target="_blank"><img src="https://opencollective.com/tsed/tiers/backer.svg?width=890"></a>
312
308
 
313
-
314
309
  ## Sponsors
315
310
 
316
311
  Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/tsed#sponsor)]
@@ -1,10 +1,7 @@
1
1
  {
2
2
  "_id": "5e972ae7a1a692917cf54f9e",
3
3
  "type": "resource",
4
- "tags": [
5
- "common",
6
- "products"
7
- ],
4
+ "tags": ["common", "products"],
8
5
  "owner": null,
9
6
  "components": [
10
7
  {
@@ -430,70 +427,41 @@
430
427
  "modified": "2020-04-15T15:40:23.647Z",
431
428
  "access": [
432
429
  {
433
- "roles": [
434
- "5e97026c50bcd9815878809a",
435
- "5e97026c50bcd98158788099",
436
- "5e97026c50bcd98158788098"
437
- ],
430
+ "roles": ["5e97026c50bcd9815878809a", "5e97026c50bcd98158788099", "5e97026c50bcd98158788098"],
438
431
  "type": "read_all"
439
432
  }
440
433
  ],
441
434
  "submissionAccess": [
442
435
  {
443
- "roles": [
444
- "5e97026c50bcd98158788098",
445
- "5e97026c50bcd98158788099"
446
- ],
436
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
447
437
  "type": "create_all"
448
438
  },
449
439
  {
450
- "roles": [
451
- "5e97026c50bcd98158788098",
452
- "5e97026c50bcd98158788099",
453
- "5e97026c50bcd9815878809a"
454
- ],
440
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099", "5e97026c50bcd9815878809a"],
455
441
  "type": "read_all"
456
442
  },
457
443
  {
458
- "roles": [
459
- "5e97026c50bcd98158788098",
460
- "5e97026c50bcd98158788099"
461
- ],
444
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
462
445
  "type": "update_all"
463
446
  },
464
447
  {
465
- "roles": [
466
- "5e97026c50bcd98158788098",
467
- "5e97026c50bcd98158788099"
468
- ],
448
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
469
449
  "type": "delete_all"
470
450
  },
471
451
  {
472
- "roles": [
473
- "5e97026c50bcd98158788098",
474
- "5e97026c50bcd98158788099"
475
- ],
452
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
476
453
  "type": "create_own"
477
454
  },
478
455
  {
479
- "roles": [
480
- "5e97026c50bcd98158788098",
481
- "5e97026c50bcd98158788099"
482
- ],
456
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
483
457
  "type": "read_own"
484
458
  },
485
459
  {
486
- "roles": [
487
- "5e97026c50bcd98158788098",
488
- "5e97026c50bcd98158788099"
489
- ],
460
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
490
461
  "type": "update_own"
491
462
  },
492
463
  {
493
- "roles": [
494
- "5e97026c50bcd98158788098",
495
- "5e97026c50bcd98158788099"
496
- ],
464
+ "roles": ["5e97026c50bcd98158788098", "5e97026c50bcd98158788099"],
497
465
  "type": "delete_own"
498
466
  }
499
467
  ],
@@ -2041,4 +2041,4 @@
2041
2041
  }
2042
2042
  ],
2043
2043
  "display": "form"
2044
- }
2044
+ }
@@ -8,9 +8,7 @@ describe("ActionsTable", () => {
8
8
  it("should render the table actions", async () => {
9
9
  const onAddAction = jest.fn();
10
10
 
11
- const { getByRole, getAllByRole } = render(
12
- <Sandbox {...Sandbox.args} onAddAction={onAddAction} />
13
- );
11
+ const { getByRole, getAllByRole } = render(<Sandbox {...Sandbox.args} onAddAction={onAddAction} />);
14
12
 
15
13
  const btn = getByRole("button", { name: /add action/i });
16
14
  const cells = getAllByRole("cell");
@@ -27,9 +25,7 @@ describe("ActionsTable", () => {
27
25
  it("should not call addAction when the default item is selected", async () => {
28
26
  const onAddAction = jest.fn();
29
27
 
30
- const { getByRole } = render(
31
- <Sandbox {...Sandbox.args} onAddAction={onAddAction} />
32
- );
28
+ const { getByRole } = render(<Sandbox {...Sandbox.args} onAddAction={onAddAction} />);
33
29
 
34
30
  const btn = getByRole("button", { name: /add action/i });
35
31
 
@@ -39,17 +35,12 @@ describe("ActionsTable", () => {
39
35
  it("should call addAction with the selected action", async () => {
40
36
  const onAddAction = jest.fn();
41
37
 
42
- const { getByRole } = render(
43
- <Sandbox {...Sandbox.args} onAddAction={onAddAction} />
44
- );
38
+ const { getByRole } = render(<Sandbox {...Sandbox.args} onAddAction={onAddAction} />);
45
39
 
46
40
  const btn = getByRole("button", { name: /add action/i });
47
41
  const select = getByRole("combobox");
48
42
 
49
- await userEvent.selectOptions(
50
- select,
51
- String(Sandbox.args.availableActions[1].value)
52
- );
43
+ await userEvent.selectOptions(select, String(Sandbox.args.availableActions[1].value));
53
44
 
54
45
  await fireEvent.click(btn);
55
46
 
@@ -32,19 +32,12 @@ export function ActionsTable({
32
32
  }, []);
33
33
 
34
34
  return (
35
- <Table
36
- {...props}
37
- disableFilters={disableFilters}
38
- disablePagination={disablePagination}
39
- columns={columns}
40
- >
35
+ <Table {...props} disableFilters={disableFilters} disablePagination={disablePagination} columns={columns}>
41
36
  <div className={"pagination-group"}>
42
37
  <Select
43
38
  name={"actions"}
44
39
  value={currentAction}
45
- choices={[{ label: i18n("Select an action"), value: "" }].concat(
46
- availableActions
47
- )}
40
+ choices={[{ label: i18n("Select an action"), value: "" }].concat(availableActions)}
48
41
  onChange={(name: string, action: string) => setAction(action)}
49
42
  />
50
43
  <div className={"pl-3"}>
@@ -55,8 +48,7 @@ export function ActionsTable({
55
48
  onClick={() => currentAction && onAddAction(currentAction)}
56
49
  type={"submit"}
57
50
  >
58
- <i className={classnames(iconClass(undefined, "plus"), "mr-1")} />{" "}
59
- {i18n("Add action")}
51
+ <i className={classnames(iconClass(undefined, "plus"), "mr-1")} /> {i18n("Add action")}
60
52
  </button>
61
53
  </div>
62
54
  </div>
@@ -0,0 +1,97 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react";
3
+ import { Sandbox } from "./alert.stories";
4
+
5
+ describe("Alert component", () => {
6
+ it("should NOT display the alert component when no error is received.", () => {
7
+ const { container } = render(<Sandbox {...Sandbox.args} error={null} />);
8
+
9
+ expect(container).toBeEmptyDOMElement();
10
+ });
11
+
12
+ it("should display an error when the error is in string format", () => {
13
+ const error = "error in string format";
14
+ const { getByRole } = render(<Sandbox {...Sandbox.args} error={error} />);
15
+
16
+ const alert = getByRole("alert") as HTMLDivElement;
17
+
18
+ expect(alert).toBeInTheDocument();
19
+ expect(alert).toHaveClass("alert alert-danger");
20
+ expect(alert).toHaveTextContent(error);
21
+ });
22
+
23
+ it("should display error(s) when the error is an array", () => {
24
+ const arrayOfErrors = ["first error", "second error", "third error"];
25
+ const joinedErrors = arrayOfErrors.map((error) => error).join("");
26
+ const { getByRole, getByText } = render(<Sandbox {...Sandbox.args} error={arrayOfErrors} />);
27
+
28
+ const alert = getByRole("alert") as HTMLDivElement;
29
+
30
+ expect(alert).toBeInTheDocument();
31
+ expect(alert).toHaveClass("alert alert-danger");
32
+ expect(getByText(joinedErrors)).toBeInTheDocument();
33
+ });
34
+
35
+ it("should display error's names paths and messages when the error is an object that has an 'errors' property that contains an array of error objects", () => {
36
+ const arrayOfErrors = {
37
+ errors: [
38
+ { name: "first error", path: "/path", message: "message" },
39
+ { name: "second error", path: "/path", message: "message" },
40
+ { name: "third error", path: "/path", message: "message" }
41
+ ]
42
+ };
43
+ const { getByRole } = render(<Sandbox {...Sandbox.args} error={arrayOfErrors} />);
44
+
45
+ const alert = getByRole("alert") as HTMLDivElement;
46
+
47
+ expect(alert).toBeInTheDocument();
48
+ expect(alert).toHaveClass("alert alert-danger");
49
+ expect(alert).toHaveTextContent(arrayOfErrors.errors.map((error) => `${error.name} (${error.path}) - ${error.message}`).join(""));
50
+ });
51
+
52
+ it("should display an error message when the error is a standard error", () => {
53
+ const standardError = { message: "first error" };
54
+ const { getByRole, getByText } = render(<Sandbox {...Sandbox.args} error={standardError} />);
55
+
56
+ const alert = getByRole("alert") as HTMLDivElement;
57
+
58
+ expect(alert).toBeInTheDocument();
59
+ expect(alert).toHaveClass("alert alert-danger");
60
+ expect(getByText(standardError.message)).toBeInTheDocument();
61
+ });
62
+
63
+ it("should display error(s) message(s) when the error is a joi validation error", () => {
64
+ const joiValidationError = { name: "ValidationError", details: [{ message: "message 1" }, { message: "message 2" }] };
65
+ const { getByRole, getByText } = render(<Sandbox {...Sandbox.args} error={joiValidationError} />);
66
+
67
+ const alert = getByRole("alert") as HTMLDivElement;
68
+
69
+ expect(alert).toBeInTheDocument();
70
+ expect(alert).toHaveClass("alert alert-danger");
71
+ expect(getByText("message 1")).toBeInTheDocument();
72
+ expect(getByText("message 2")).toBeInTheDocument();
73
+ });
74
+
75
+ it("should display a custom error message that asks to reload the form when a conflict error occurs in a form", () => {
76
+ const error = { _id: "some id", display: "some value" };
77
+ const messageReturned = "Another user has saved this form already. Please reload and re-apply your changes.";
78
+ const { getByRole } = render(<Sandbox {...Sandbox.args} error={error} />);
79
+
80
+ const alert = getByRole("alert") as HTMLDivElement;
81
+
82
+ expect(alert).toBeInTheDocument();
83
+ expect(alert).toHaveClass("alert alert-danger");
84
+ expect(alert).toHaveTextContent(messageReturned);
85
+ });
86
+
87
+ it("should display an error message by default when the error format does not match any of the conditions of the formatError() handler", () => {
88
+ const messageError: string = "An error occurred. See console logs for details.";
89
+ const { getByRole } = render(<Sandbox {...Sandbox.args} error={true} />);
90
+
91
+ const alert = getByRole("alert") as HTMLDivElement;
92
+
93
+ expect(alert).toBeInTheDocument();
94
+ expect(alert).toHaveClass("alert alert-danger");
95
+ expect(alert).toHaveTextContent(messageError);
96
+ });
97
+ });
@@ -29,20 +29,14 @@ function formatError(error: any): any {
29
29
  }
30
30
 
31
31
  // If this is a joy validation error.
32
- if (
33
- Object.prototype.hasOwnProperty.call(error, "name") &&
34
- error.name === "ValidationError"
35
- ) {
32
+ if (Object.prototype.hasOwnProperty.call(error, "name") && error.name === "ValidationError") {
36
33
  return error.details.map((item: any, index: number) => {
37
34
  return <div key={index}>{item.message}</div>;
38
35
  });
39
36
  }
40
37
 
41
38
  // If a conflict error occurs on a form, the form is returned.
42
- if (
43
- Object.prototype.hasOwnProperty.call(error, "_id") &&
44
- Object.prototype.hasOwnProperty.call(error, "display")
45
- ) {
39
+ if (Object.prototype.hasOwnProperty.call(error, "_id") && Object.prototype.hasOwnProperty.call(error, "display")) {
46
40
  return "Another user has saved this form already. Please reload and re-apply your changes.";
47
41
  }
48
42
 
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { Alert } from "./alert.component";
3
+
4
+ export default {
5
+ title: "ReactFormio/Alert",
6
+ component: Alert,
7
+ argTypes: {},
8
+ parameters: {}
9
+ };
10
+
11
+ export const Sandbox = (args: any) => {
12
+ return <Alert {...args} />;
13
+ };
14
+
15
+ Sandbox.args = {
16
+ error: "error placeholder"
17
+ };