@ouroboros/mouth-mui 2.1.1 → 2.1.3

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 (29) hide show
  1. package/README.md +80 -10
  2. package/lib/components/pages/Locales.d.ts +2 -2
  3. package/lib/components/pages/Locales.js +62 -48
  4. package/lib/components/pages/Templates/Create.d.ts +2 -2
  5. package/lib/components/pages/Templates/Create.js +17 -14
  6. package/lib/components/pages/Templates/Template/Content/Create/index.d.ts +1 -1
  7. package/lib/components/pages/Templates/Template/Content/Create/index.js +44 -32
  8. package/lib/components/pages/Templates/Template/Content/Preview/index.d.ts +2 -2
  9. package/lib/components/pages/Templates/Template/Content/Preview/index.js +15 -2
  10. package/lib/components/pages/Templates/Template/Content/Update/index.d.ts +1 -1
  11. package/lib/components/pages/Templates/Template/Content/Update/index.js +36 -26
  12. package/lib/components/pages/Templates/Template/Content/View/index.d.ts +2 -2
  13. package/lib/components/pages/Templates/Template/Content/View/index.js +1 -1
  14. package/lib/components/pages/Templates/Template/index.d.ts +2 -2
  15. package/lib/components/pages/Templates/Template/index.js +18 -10
  16. package/lib/components/pages/Templates/index.d.ts +4 -4
  17. package/lib/components/pages/Templates/index.js +16 -8
  18. package/lib/locales.js +18 -15
  19. package/package.json +9 -10
  20. package/releases.md +21 -0
  21. package/src/components/pages/Locales.tsx +61 -46
  22. package/src/components/pages/Templates/Create.tsx +21 -17
  23. package/src/components/pages/Templates/Template/Content/Create/index.tsx +48 -38
  24. package/src/components/pages/Templates/Template/Content/Preview/index.tsx +20 -5
  25. package/src/components/pages/Templates/Template/Content/Update/index.tsx +38 -28
  26. package/src/components/pages/Templates/Template/Content/View/index.tsx +2 -2
  27. package/src/components/pages/Templates/Template/index.tsx +20 -13
  28. package/src/components/pages/Templates/index.tsx +20 -12
  29. package/src/locales.ts +25 -22
@@ -76,18 +76,26 @@ export default function Template({ locales, onChange, onError, onContent, rights
76
76
  // Called to update the template
77
77
  function update() {
78
78
  // Create the data in the system
79
- mouth.update('template', edit).then((data) => {
79
+ mouth.update('template', edit).then((res) => {
80
+ // If we failed
81
+ if (res.error) {
82
+ if (res.error.code === errors.body.DB_DUPLICATE) {
83
+ refName.current?.error('Duplicate');
84
+ }
85
+ else {
86
+ if (onError) {
87
+ onError(res.error);
88
+ }
89
+ else {
90
+ throw new Error(JSON.stringify(res.error));
91
+ }
92
+ }
93
+ return;
94
+ }
80
95
  // Hide the form
81
96
  editSet(false);
82
97
  // Let the parent know
83
98
  onChange(edit);
84
- }, (error) => {
85
- if (error.code === errors.body.DB_DUPLICATE) {
86
- refName.current?.error('Duplicate');
87
- }
88
- else {
89
- return false;
90
- }
91
99
  });
92
100
  }
93
101
  // View toggle
@@ -99,7 +107,7 @@ export default function Template({ locales, onChange, onError, onContent, rights
99
107
  if (contents === false) {
100
108
  mouth.read('template/contents', {
101
109
  template: value._id
102
- }).then(contentsSet);
110
+ }).then((res) => contentsSet(res.data));
103
111
  }
104
112
  viewSet(true);
105
113
  }
@@ -163,7 +171,7 @@ export default function Template({ locales, onChange, onError, onContent, rights
163
171
  Template.propTypes = {
164
172
  locales: PropTypes.objectOf(PropTypes.string).isRequired,
165
173
  onChange: PropTypes.func.isRequired,
166
- onError: PropTypes.func.isRequired,
174
+ onError: PropTypes.func,
167
175
  onContent: PropTypes.func.isRequired,
168
176
  rights: PropTypes.exact({
169
177
  template: PropTypes.exact({
@@ -10,8 +10,8 @@ import PropTypes from 'prop-types';
10
10
  import React from 'react';
11
11
  import { responseErrorStruct } from '@ouroboros/body';
12
12
  export type TemplatesProps = {
13
- onError: (error: responseErrorStruct) => void;
14
- onSuccess: (type: string) => void;
13
+ onError?: (error: responseErrorStruct) => void;
14
+ onSuccess?: (type: string) => void;
15
15
  };
16
16
  /**
17
17
  * Templates
@@ -26,8 +26,8 @@ export type TemplatesProps = {
26
26
  declare function Templates({ onError, onSuccess }: TemplatesProps): React.JSX.Element;
27
27
  declare namespace Templates {
28
28
  var propTypes: {
29
- onError: PropTypes.Validator<(...args: any[]) => any>;
30
- onSuccess: PropTypes.Validator<(...args: any[]) => any>;
29
+ onError: PropTypes.Requireable<(...args: any[]) => any>;
30
+ onSuccess: PropTypes.Requireable<(...args: any[]) => any>;
31
31
  };
32
32
  }
33
33
  export default Templates;
@@ -42,14 +42,14 @@ export default function Templates({ onError, onSuccess }) {
42
42
  useEffect(() => {
43
43
  // If we have template read permissions
44
44
  if (rightsTemplate.read) {
45
- mouth.read('locales').then((data) => {
45
+ mouth.read('locales').then((res) => {
46
46
  const oLocales = {};
47
- for (const o of data) {
47
+ for (const o of res.data) {
48
48
  oLocales[o._id] = o.name;
49
49
  }
50
50
  localesSet(oLocales);
51
51
  });
52
- mouth.read('templates').then(templatesSet);
52
+ mouth.read('templates').then((res) => templatesSet(res.data));
53
53
  }
54
54
  else {
55
55
  localesSet({});
@@ -63,7 +63,9 @@ export default function Templates({ onError, onSuccess }) {
63
63
  // Called when a template has been created
64
64
  function templateCreated(template) {
65
65
  // Notify parent
66
- onSuccess('template_create');
66
+ if (onSuccess) {
67
+ onSuccess('template_create');
68
+ }
67
69
  // Hide the create form
68
70
  createSet(false);
69
71
  // Clone the current templates, add the new one to the front, and set
@@ -73,7 +75,9 @@ export default function Templates({ onError, onSuccess }) {
73
75
  // Called when a template has been updated
74
76
  function templateUpdated(template) {
75
77
  // Notify parent
76
- onSuccess('template_update');
78
+ if (onSuccess) {
79
+ onSuccess('template_update');
80
+ }
77
81
  // Work on latest
78
82
  templatesSet(l => arrayFindOverwrite(l, '_id', template._id, template, true));
79
83
  }
@@ -88,13 +92,17 @@ export default function Templates({ onError, onSuccess }) {
88
92
  React.createElement("i", { className: 'fa-solid fa-plus' + (create ? ' open' : '') }))))),
89
93
  create &&
90
94
  React.createElement(Create, { onCancel: () => createSet(false), onCreated: templateCreated, onError: onError }),
91
- templates.map((o) => React.createElement(Template, { key: o._id, locales: locales, onChange: templateUpdated, onContent: type => onSuccess(`content_${type}`), onError: onError, rights: {
95
+ templates.map((o) => React.createElement(Template, { key: o._id, locales: locales, onChange: templateUpdated, onContent: type => {
96
+ if (onSuccess) {
97
+ onSuccess(`content_${type}`);
98
+ }
99
+ }, onError: onError, rights: {
92
100
  content: rightsContent,
93
101
  template: rightsTemplate
94
102
  }, value: o }))));
95
103
  }
96
104
  // Valid props
97
105
  Templates.propTypes = {
98
- onError: PropTypes.func.isRequired,
99
- onSuccess: PropTypes.func.isRequired
106
+ onError: PropTypes.func,
107
+ onSuccess: PropTypes.func
100
108
  };
package/lib/locales.js CHANGED
@@ -139,28 +139,31 @@ class Locales extends Subscribe {
139
139
  // Mark us as running
140
140
  this.fetching = true;
141
141
  // Fetch the data from the server
142
- mouth.read('locales').then((list) => {
142
+ mouth.read('locales').then((res) => {
143
+ // If we failed
144
+ if (res.error) {
145
+ // If we haven't hit the limit
146
+ if (this.failed < 3) {
147
+ // Increase the failed count
148
+ ++this.failed;
149
+ // Fetch again
150
+ this.fetch();
151
+ }
152
+ // Else, we can't keep trying, notify the user
153
+ else {
154
+ events.get('error').trigger(res.error);
155
+ }
156
+ return;
157
+ }
143
158
  // If there's data
144
- if (list) {
159
+ if (res.data) {
145
160
  // Trigger all callbacks
146
- this.set(list);
161
+ this.set(res.data);
147
162
  }
148
163
  // Finish running
149
164
  this.fetching = false;
150
165
  // Reset the count
151
166
  this.failed = 0;
152
- }, error => {
153
- // If we haven't hit the limit
154
- if (this.failed < 3) {
155
- // Increase the failed count
156
- ++this.failed;
157
- // Fetch again
158
- this.fetch();
159
- }
160
- // Else, we can't keep trying, notify the user
161
- else {
162
- events.get('error').trigger(error);
163
- }
164
167
  }).finally(() => {
165
168
  // Regardless of the outcome, we're done fetching
166
169
  this.fetching = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouroboros/mouth-mui",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Components for use with the Mouth service",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -28,27 +28,26 @@
28
28
  "devDependencies": {
29
29
  "@types/node": "^18.14.0",
30
30
  "@types/react": "^18.0.28",
31
- "@types/uuid": "^9.0.0",
32
31
  "tslint": "^6.1.3",
33
32
  "tslint-config-prettier": "^1.18.0",
34
- "typescript": "^4.8.3"
33
+ "typescript": "^5.9.3"
35
34
  },
36
35
  "dependencies": {
37
36
  "@ouroboros/define": "^1.1.3",
38
37
  "@ouroboros/define-mui": "^1.5.6",
39
- "@ouroboros/mouth": "^2.1.1",
38
+ "@ouroboros/mouth": "^2.2.0",
40
39
  "@ouroboros/react-radiobuttons-mui": "^1.1.0",
41
40
  "@ouroboros/subscribe": "^1.3.2",
42
- "@ouroboros/tools": "^0.7.0",
41
+ "@ouroboros/tools": "^0.7.3",
43
42
  "prop-types": "^15.8.1"
44
43
  },
45
44
  "peerDependencies": {
46
- "@emotion/react": "^11.8.2",
47
- "@emotion/styled": "^11.8.1",
45
+ "@emotion/react": "^11.14.0",
46
+ "@emotion/styled": "^11.14.1",
48
47
  "@mui/material": "^5.5.1",
49
- "@ouroboros/body": "^1.2.0",
50
- "@ouroboros/brain-react": "^2.3.1",
51
- "@ouroboros/events": "^1.1.0",
48
+ "@ouroboros/body": "^1.3.0",
49
+ "@ouroboros/brain-react": "^2.3.3",
50
+ "@ouroboros/events": "^1.1.3",
52
51
  "react": "^17.0.2 || ^18.0.0",
53
52
  "react-dom": "^17.0.2 || ^18.0.0"
54
53
  }
package/releases.md ADDED
@@ -0,0 +1,21 @@
1
+ # @ouroboros/mouth-mui releases
2
+
3
+ ## 2.1.3
4
+ - Updated `@ouroboros/body` and `@ouroboros/mouth` to latest
5
+
6
+ ## 2.1.2
7
+ - Completed documentation.
8
+
9
+ ## 2.1.1
10
+ - Updated @ouroboros/mouth to 2.1.1.
11
+ - Updated @ouroboros/body to 1.2.0.
12
+ - Updated @ouroboros/brain-react to 2.3.1.
13
+
14
+ ## 2.1.0
15
+ - Updated @ouroboros/brain-react to 2.3.0.
16
+ - Updated @ouroboros/define to 1.1.3.
17
+ - Updated @ouroboros/define-mui to 1.5.6.
18
+ - Updated @ouroboros/mouth to 2.1.0.
19
+ - Removed the `mobile` prop from all components as it wasn't used.
20
+ - Removed all uses of clone from the project.
21
+ - Added a shared file for holding onto common types / defines.
@@ -42,7 +42,7 @@ const LocaleTree = new Tree(LocaleDef, {
42
42
  });
43
43
 
44
44
  // Types
45
- import { responseErrorStruct } from '@ouroboros/body';
45
+ import { responseErrorStruct, responseStruct } from '@ouroboros/body';
46
46
  export type LocalesProps = {
47
47
  onError: (error: responseErrorStruct) => void,
48
48
  onSuccess: (type: string) => void
@@ -72,9 +72,9 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
72
72
 
73
73
  // If we have read rights
74
74
  if(rights.read) {
75
- mouth.read('locales').then(recordsSet);
75
+ mouth.read('locales').then((res: responseStruct) => recordsSet(res.data));
76
76
  } else {
77
- recordsSet([]);
77
+ recordsSet([ ]);
78
78
  }
79
79
 
80
80
  // If we don't have create rights
@@ -91,13 +91,31 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
91
91
  return new Promise((resolve, reject) => {
92
92
 
93
93
  // Create the new locale
94
- mouth.create('locale', locale).then((data: string) => {
94
+ mouth.create('locale', locale).then((res: responseStruct) => {
95
+
96
+ // If we failed
97
+ if(res.error) {
98
+ if(res.error.code === errors.body.DB_NO_RECORD) {
99
+ return reject([['_id', 'Already in use']]);
100
+ } else if(res.error.code === errors.body.DATA_FIELDS) {
101
+ return reject(res.error.msg);
102
+ } else {
103
+ if(onError) {
104
+ onError(res.error);
105
+ return reject([ ]);
106
+ } else {
107
+ throw new Error(JSON.stringify(res.error));
108
+ }
109
+ }
110
+ }
95
111
 
96
112
  // If we were successful
97
- if(data) {
113
+ if(res.data) {
98
114
 
99
115
  // Notify the parent
100
- onSuccess('create');
116
+ if(onSuccess) {
117
+ onSuccess('create');
118
+ }
101
119
 
102
120
  // Close the create form
103
121
  createSet(false);
@@ -112,20 +130,7 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
112
130
  }
113
131
 
114
132
  // Resolve with the form
115
- resolve(data ? true : false);
116
-
117
- }, (error: responseErrorStruct) => {
118
- if(error.code === errors.body.DB_NO_RECORD) {
119
- reject([['_id', 'Already in use']]);
120
- } else if(error.code === errors.body.DATA_FIELDS) {
121
- reject(error.msg);
122
- } else {
123
- if(onError) {
124
- onError(error);
125
- } else {
126
- throw new Error(JSON.stringify(error));
127
- }
128
- }
133
+ resolve(res.data ? true : false);
129
134
  });
130
135
  });
131
136
  }
@@ -134,13 +139,24 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
134
139
  function deleteClick(key: string) {
135
140
 
136
141
  // Delete the existing locale
137
- mouth.delete('locale', { _id: key }).then((data: boolean) => {
142
+ mouth.delete('locale', { _id: key }).then((res: responseStruct) => {
143
+
144
+ // If we failed
145
+ if(res.error) {
146
+ if(onError) {
147
+ return onError(res.error);
148
+ } else {
149
+ throw new Error(JSON.stringify(res.error));
150
+ }
151
+ }
138
152
 
139
153
  // If it was successful
140
- if(data) {
154
+ if(res.data) {
141
155
 
142
156
  // Notify the parent
143
- onSuccess('delete');
157
+ if(onSuccess) {
158
+ onSuccess('delete');
159
+ }
144
160
 
145
161
  // Look for the record
146
162
  const i = afindi(records, '_id', key);
@@ -158,12 +174,6 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
158
174
  locales.set(lRecords);
159
175
  }
160
176
  }
161
- }, (error: responseErrorStruct) => {
162
- if(onError) {
163
- onError(error);
164
- } else {
165
- throw new Error(JSON.stringify(error));
166
- }
167
177
  });
168
178
  }
169
179
 
@@ -177,13 +187,29 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
177
187
  return new Promise((resolve, reject) => {
178
188
 
179
189
  // Update the locale on the server
180
- mouth.update('locale', locale).then((data: boolean) => {
190
+ mouth.update('locale', locale).then((res: responseStruct) => {
191
+
192
+ // If we failed
193
+ if(res.error) {
194
+ if(res.error.code === errors.body.DATA_FIELDS) {
195
+ return reject(res.error.msg);
196
+ } else {
197
+ if(onError) {
198
+ onError(res.error);
199
+ return reject([ ]);
200
+ } else {
201
+ throw new Error(JSON.stringify(res.error));
202
+ }
203
+ }
204
+ }
181
205
 
182
206
  // If we were successful
183
- if(data) {
207
+ if(res.data) {
184
208
 
185
209
  // Notify the parent
186
- onSuccess('update');
210
+ if(onSuccess) {
211
+ onSuccess('update');
212
+ }
187
213
 
188
214
  // Look for the record
189
215
  const i = afindi(records, '_id', key);
@@ -203,18 +229,7 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
203
229
  }
204
230
 
205
231
  // Resolve with the Form
206
- resolve(data);
207
-
208
- }, (error: responseErrorStruct) => {
209
- if(error.code === errors.body.DATA_FIELDS) {
210
- reject(error.msg);
211
- } else {
212
- if(onError) {
213
- onError(error);
214
- } else {
215
- throw new Error(JSON.stringify(error));
216
- }
217
- }
232
+ resolve(res.data);
218
233
  });
219
234
  });
220
235
  }
@@ -262,6 +277,6 @@ export default function Locales({ onError, onSuccess }: LocalesProps) {
262
277
 
263
278
  // Valid props
264
279
  Locales.propTypes = {
265
- onError: PropTypes.func.isRequired,
266
- onSuccess: PropTypes.func.isRequired
280
+ onError: PropTypes.func,
281
+ onSuccess: PropTypes.func
267
282
  }
@@ -30,12 +30,12 @@ import Variables from './Template/Variables';
30
30
  const oNameNode = new Node(TemplateDef.name);
31
31
 
32
32
  // Types
33
- import { responseErrorStruct } from '@ouroboros/body';
33
+ import { responseErrorStruct, responseStruct } from '@ouroboros/body';
34
34
  import { templateStruct } from './Template';
35
35
  export interface CreateProps {
36
36
  onCancel?: () => void,
37
37
  onCreated: (template: templateStruct) => void,
38
- onError: (error: responseErrorStruct) => void
38
+ onError?: (error: responseErrorStruct) => void
39
39
  }
40
40
 
41
41
  /**
@@ -53,7 +53,7 @@ export default function Create({ onCancel, onCreated, onError }: CreateProps) {
53
53
  // State
54
54
  const [ record, recordSet ] = useState<templateStruct>({
55
55
  name: '',
56
- variables: {}
56
+ variables: { }
57
57
  });
58
58
 
59
59
  // Refs
@@ -72,24 +72,28 @@ export default function Create({ onCancel, onCreated, onError }: CreateProps) {
72
72
  function create() {
73
73
 
74
74
  // Create the data in the system
75
- mouth.create('template', record).then((data: string) => {
75
+ mouth.create('template', record).then((res: responseStruct) => {
76
+
77
+ // If we failed
78
+ if(res.error) {
79
+ if(res.error.code === errors.body.DB_DUPLICATE) {
80
+ refName.current?.error('Duplicate');
81
+ } else {
82
+ if(onError) {
83
+ onError(res.error);
84
+ return;
85
+ } else {
86
+ throw new Error(JSON.stringify(res.error));
87
+ }
88
+ }
89
+ }
76
90
 
77
91
  // Add the ID to the record
78
- record._id = data;
92
+ record._id = res.data;
79
93
 
80
94
  // Let the parent know
81
95
  onCreated({ ...record });
82
- }, (error: responseErrorStruct) => {
83
- if(error.code === errors.body.DB_DUPLICATE) {
84
- refName.current?.error('Duplicate');
85
- } else {
86
- if(onError) {
87
- onError(error);
88
- } else {
89
- throw new Error(JSON.stringify(error));
90
- }
91
- }
92
- })
96
+ });
93
97
  }
94
98
 
95
99
  // Render
@@ -132,5 +136,5 @@ export default function Create({ onCancel, onCreated, onError }: CreateProps) {
132
136
  Create.propTypes = {
133
137
  onCancel: PropTypes.func,
134
138
  onCreated: PropTypes.func.isRequired,
135
- onError: PropTypes.func.isRequired,
139
+ onError: PropTypes.func,
136
140
  }
@@ -32,11 +32,11 @@ import SMS from './SMS';
32
32
 
33
33
  // Types
34
34
  import { contentStruct, typeOption } from '../../';
35
- import { responseErrorStruct } from '@ouroboros/body';
35
+ import { responseErrorStruct, responseStruct } from '@ouroboros/body';
36
36
  export type TemplateContentCreateProps = {
37
37
  locales: Record<string, string>,
38
38
  onCreated: (content: contentStruct) => void,
39
- onError: (error: responseErrorStruct) => void,
39
+ onError?: (error: responseErrorStruct) => void,
40
40
  template: string
41
41
  }
42
42
 
@@ -55,58 +55,66 @@ export default function Create(
55
55
  ) {
56
56
 
57
57
  // State
58
- const [fieldErrors, fieldErrorsSet] = useState<Record<string, any>>({});
59
- const [preview, previewSet] = useState(false);
60
- const [record, recordSet] = useState<Omit<contentStruct, 'type'>>({
58
+ const [ fieldErrors, fieldErrorsSet ] = useState<Record<string, any>>({});
59
+ const [ preview, previewSet ] = useState(false);
60
+ const [ record, recordSet ] = useState<Omit<contentStruct, 'type'>>({
61
61
  locale: Object.keys(locales)[0],
62
62
  template,
63
63
  subject: '',
64
64
  text: '',
65
65
  html: ''
66
66
  })
67
- const [type, typeSet] = useState<typeOption>('email');
67
+ const [ type, typeSet ] = useState<typeOption>('email');
68
68
 
69
69
  // Called to create the new content record
70
70
  function create() {
71
71
 
72
72
  // Send the record data to the server
73
- mouth.create(`template/${type}`, record).then((data: string) => {
73
+ mouth.create(`template/${type}`, record).then((res: responseStruct) => {
74
+
75
+ // If we failed
76
+ if(res.error) {
77
+ if(res.error.code === errors.body.DATA_FIELDS) {
78
+ fieldErrorsSet(errorTree(res.error.msg));
79
+ } else if(res.error.code === errors.body.DB_DUPLICATE) {
80
+ fieldErrorsSet({ locale: 'Already used' });
81
+ } else if(res.error.code === errors.TEMPLATE_CONTENT_ERROR) {
82
+ const oLines: { templates: string[], variables: string[] } = { templates: [], variables: [] };
83
+ for(const l of res.error.msg) {
84
+ if(l[0] === 'template') {
85
+ oLines.templates.push(l[1]);
86
+ } else if(l[0] === 'variable') {
87
+ oLines.variables.push(l[1]);
88
+ }
89
+ }
90
+ const lLines = [];
91
+ if(oLines.templates.length) {
92
+ lLines.push('The following templates are invalid: ' + oLines.templates.join(', '));
93
+ }
94
+ if(oLines.variables.length) {
95
+ lLines.push('The following variables are invalid: ' + oLines.variables.join(', '));
96
+ }
97
+
98
+ // Show the errors
99
+ if(onError) {
100
+ onError({ code: 0, msg: lLines.join('\n') });
101
+ } else {
102
+ throw new Error(JSON.stringify(res.error));
103
+ }
104
+ } else if(onError) {
105
+ onError(res.error);
106
+ } else {
107
+ throw new Error(JSON.stringify(res.error));
108
+ }
109
+ return;
110
+ }
74
111
 
75
112
  // Add the type and ID
76
- const oRecord = { ...record, type, _id: data }
113
+ const oRecord = { ...record, type, _id: res.data }
77
114
 
78
115
  // Tell the parent about the new record
79
116
  onCreated(oRecord);
80
117
 
81
- }, (error: responseErrorStruct) => {
82
- if(error.code === errors.body.DATA_FIELDS) {
83
- fieldErrorsSet(errorTree(error.msg));
84
- } else if(error.code === errors.body.DB_DUPLICATE) {
85
- fieldErrorsSet({ locale: 'Already used' });
86
- } else if(error.code === errors.TEMPLATE_CONTENT_ERROR) {
87
- const oLines: { templates: string[], variables: string[] } = { templates: [], variables: [] };
88
- for(const l of error.msg) {
89
- if(l[0] === 'template') {
90
- oLines.templates.push(l[1]);
91
- } else if(l[0] === 'variable') {
92
- oLines.variables.push(l[1]);
93
- }
94
- }
95
- const lLines = [];
96
- if(oLines.templates.length) {
97
- lLines.push('The following templates are invalid: ' + oLines.templates.join(', '));
98
- }
99
- if(oLines.variables.length) {
100
- lLines.push('The following variables are invalid: ' + oLines.variables.join(', '));
101
- }
102
-
103
- // Show the errors
104
- if(onError) {
105
- onError({ code: 0, msg: lLines.join('\n') });
106
- }
107
- } else {
108
- onError(error);
109
- }
110
118
  });
111
119
  }
112
120
 
@@ -227,8 +235,10 @@ export default function Create(
227
235
  onError={(error: responseErrorStruct) => {
228
236
  if(error.code === errors.body.DATA_FIELDS) {
229
237
  fieldErrorsSet(errorTree(error.msg));
230
- } else {
238
+ } else if(onError) {
231
239
  onError(error);
240
+ } else {
241
+ throw new Error(JSON.stringify(error));
232
242
  }
233
243
  previewSet(false);
234
244
  }}
@@ -27,10 +27,10 @@ import SMS from './SMS';
27
27
 
28
28
  // Types
29
29
  import { contentStruct } from '../..';
30
- import { responseErrorStruct } from '@ouroboros/body';
30
+ import { responseErrorStruct, responseStruct } from '@ouroboros/body';
31
31
  export type PreviewProps = {
32
32
  onClose: () => void,
33
- onError: (error: responseErrorStruct) => void,
33
+ onError?: (error: responseErrorStruct) => void,
34
34
  value: contentStruct
35
35
  }
36
36
 
@@ -54,8 +54,23 @@ export default function Preview({ onClose, onError, value }: PreviewProps) {
54
54
  mouth.create(
55
55
  `template/${value.type}/generate`,
56
56
  value
57
- ).then(previewSet, onError);
58
- }, [value, onError]);
57
+ ).then((res: responseStruct) => {
58
+
59
+ // If we failed
60
+ if(res.error) {
61
+ if(onError) {
62
+ onError(res.error);
63
+ return;
64
+ } else {
65
+ throw new Error(JSON.stringify(res.error));
66
+ }
67
+ }
68
+
69
+ // Set the preview
70
+ previewSet(res.data);
71
+
72
+ })
73
+ }, [ value, onError ]);
59
74
 
60
75
  // Render
61
76
  return (
@@ -91,7 +106,7 @@ export default function Preview({ onClose, onError, value }: PreviewProps) {
91
106
  // Valid props
92
107
  Preview.propTypes = {
93
108
  onClose: PropTypes.func.isRequired,
94
- onError: PropTypes.func.isRequired,
109
+ onError: PropTypes.func,
95
110
  value: PropTypes.shape({
96
111
  locale: PropTypes.string.isRequired,
97
112
  template: PropTypes.string,