@ouroboros/mouth-mui 1.3.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/lib/components/pages/Locales.d.ts +1 -3
  2. package/lib/components/pages/Locales.js +32 -23
  3. package/lib/components/pages/Templates/Create.d.ts +1 -1
  4. package/lib/components/pages/Templates/Create.js +11 -14
  5. package/lib/components/pages/Templates/Template/Content/Create/Email.d.ts +1 -1
  6. package/lib/components/pages/Templates/Template/Content/Create/Email.js +6 -10
  7. package/lib/components/pages/Templates/Template/Content/Create/SMS.d.ts +1 -1
  8. package/lib/components/pages/Templates/Template/Content/Create/SMS.js +4 -6
  9. package/lib/components/pages/Templates/Template/Content/Create/index.d.ts +1 -3
  10. package/lib/components/pages/Templates/Template/Content/Create/index.js +14 -20
  11. package/lib/components/pages/Templates/Template/Content/Preview/Email.d.ts +1 -3
  12. package/lib/components/pages/Templates/Template/Content/Preview/Email.js +6 -7
  13. package/lib/components/pages/Templates/Template/Content/Preview/SMS.d.ts +1 -3
  14. package/lib/components/pages/Templates/Template/Content/Preview/SMS.js +3 -4
  15. package/lib/components/pages/Templates/Template/Content/Preview/index.d.ts +1 -3
  16. package/lib/components/pages/Templates/Template/Content/Preview/index.js +3 -6
  17. package/lib/components/pages/Templates/Template/Content/Update/Email.d.ts +1 -1
  18. package/lib/components/pages/Templates/Template/Content/Update/Email.js +6 -11
  19. package/lib/components/pages/Templates/Template/Content/Update/SMS.d.ts +1 -1
  20. package/lib/components/pages/Templates/Template/Content/Update/SMS.js +4 -6
  21. package/lib/components/pages/Templates/Template/Content/Update/index.d.ts +1 -3
  22. package/lib/components/pages/Templates/Template/Content/Update/index.js +17 -23
  23. package/lib/components/pages/Templates/Template/Content/View/Email.d.ts +1 -3
  24. package/lib/components/pages/Templates/Template/Content/View/Email.js +6 -7
  25. package/lib/components/pages/Templates/Template/Content/View/SMS.d.ts +1 -3
  26. package/lib/components/pages/Templates/Template/Content/View/SMS.js +3 -4
  27. package/lib/components/pages/Templates/Template/Content/View/index.d.ts +1 -3
  28. package/lib/components/pages/Templates/Template/Content/View/index.js +5 -6
  29. package/lib/components/pages/Templates/Template/Variables.d.ts +1 -1
  30. package/lib/components/pages/Templates/Template/Variables.js +6 -7
  31. package/lib/components/pages/Templates/Template/index.d.ts +1 -3
  32. package/lib/components/pages/Templates/Template/index.js +27 -45
  33. package/lib/components/pages/Templates/index.d.ts +1 -3
  34. package/lib/components/pages/Templates/index.js +9 -21
  35. package/lib/shared.d.ts +12 -0
  36. package/lib/shared.js +25 -0
  37. package/package.json +7 -8
  38. package/src/components/pages/Locales.tsx +40 -27
  39. package/src/components/pages/Templates/Create.tsx +12 -15
  40. package/src/components/pages/Templates/Template/Content/Create/Email.tsx +15 -19
  41. package/src/components/pages/Templates/Template/Content/Create/SMS.tsx +7 -9
  42. package/src/components/pages/Templates/Template/Content/Create/index.tsx +15 -23
  43. package/src/components/pages/Templates/Template/Content/Preview/Email.tsx +7 -9
  44. package/src/components/pages/Templates/Template/Content/Preview/SMS.tsx +3 -9
  45. package/src/components/pages/Templates/Template/Content/Preview/index.tsx +2 -9
  46. package/src/components/pages/Templates/Template/Content/Update/Email.tsx +15 -18
  47. package/src/components/pages/Templates/Template/Content/Update/SMS.tsx +7 -9
  48. package/src/components/pages/Templates/Template/Content/Update/index.tsx +19 -29
  49. package/src/components/pages/Templates/Template/Content/View/Email.tsx +6 -8
  50. package/src/components/pages/Templates/Template/Content/View/SMS.tsx +3 -5
  51. package/src/components/pages/Templates/Template/Content/View/index.tsx +9 -12
  52. package/src/components/pages/Templates/Template/Variables.tsx +6 -7
  53. package/src/components/pages/Templates/Template/index.tsx +37 -59
  54. package/src/components/pages/Templates/index.tsx +19 -31
  55. package/src/shared.ts +29 -0
  56. package/ouroboros-mouth-mui-1.3.2.tgz +0 -0
  57. package/src/types/xhr2.d.ts +0 -3
@@ -8,12 +8,11 @@
8
8
  */
9
9
 
10
10
  // Ouroboros modules
11
- import clone from '@ouroboros/clone';
12
11
  import { Node } from '@ouroboros/define';
13
12
  import { DefineNode } from '@ouroboros/define-mui';
14
13
  import mouth, { errors } from '@ouroboros/mouth';
15
- import TemplateDef from '@ouroboros/mouth/definitions/template.json';
16
- import { afindi, omap, ucfirst } from '@ouroboros/tools';
14
+ import TemplateDef from '@ouroboros/mouth/define/template.json';
15
+ import { arrayFindMerge, omap, ucfirst } from '@ouroboros/tools';
17
16
 
18
17
  // NPM modules
19
18
  import PropTypes from 'prop-types';
@@ -61,7 +60,6 @@ export type templateStruct = {
61
60
  export type typeOption = 'email' | 'sms';
62
61
  export type TemplateProps = {
63
62
  locales: Record<string, string>,
64
- mobile: boolean,
65
63
  onChange: (template: templateStruct) => void,
66
64
  onError: (error: responseErrorStruct) => void,
67
65
  onContent: (type: string) => void,
@@ -85,62 +83,46 @@ const oNameNode = new Node(TemplateDef.name);
85
83
  * @param Object props Properties passed to the component
86
84
  * @returns React.Component
87
85
  */
88
- export default function Template(props: TemplateProps) {
86
+ export default function Template(
87
+ { locales, onChange, onError, onContent, rights, value }: TemplateProps
88
+ ) {
89
89
 
90
90
  // State
91
- const [contents, contentsSet] = useState<contentStruct[] | false>(false);
92
- const [tab, tabSet] = useState<number>(0);
93
- const [edit, editSet] = useState<templateStruct | false>(false);
94
- const [view, viewSet] = useState<boolean>(false);
91
+ const [ contents, contentsSet ] = useState<contentStruct[] | false>(false);
92
+ const [ tab, tabSet ] = useState<number>(0);
93
+ const [ edit, editSet ] = useState<templateStruct | false>(false);
94
+ const [ view, viewSet ] = useState<boolean>(false);
95
95
 
96
96
  // Refs
97
97
  const refName = useRef<DefineNode>(null);
98
98
 
99
99
  // Called when the update record changes
100
- function change(field: string, value: any) {
100
+ function change(field: string, val: any) {
101
101
 
102
102
  // Set the new record
103
- editSet(o => {
104
- const oRecord = clone(o);
105
- oRecord[field] = value;
106
- return oRecord;
107
- });
103
+ editSet(o => { return { ...o as templateStruct, [field]: val } });
108
104
  }
109
105
 
110
106
  // Called when a single conent record is created
111
107
  function contentCreated(content: contentStruct) {
112
108
 
113
109
  // Notify the parent
114
- props.onContent('create');
110
+ onContent('create');
115
111
 
116
- // Clone the current contents
117
- const lContents = clone(contents);
118
-
119
- // Add the new record to the end of the array
120
- lContents.push(content);
121
-
122
- // Set the new contents
123
- contentsSet(lContents);
112
+ // Add it to the end
113
+ contentsSet(l => [ ...l as contentStruct[], content ]);
124
114
  }
125
115
 
126
116
  // Called when a single content record is updated
127
117
  function contentUpdated(content: contentStruct) {
128
118
 
129
119
  // Notify the parent
130
- props.onContent('update');
131
-
132
- // Find the index of the record
133
- const i = afindi(contents as contentStruct[], '_id', content._id);
120
+ onContent('update');
134
121
 
135
- // If we got an index
136
- if(i > -1) {
137
-
138
- // Clone the current contents, merge the current record with the
139
- // new one, and set the new contents
140
- const lContents = clone(contents);
141
- lContents[i] = {...lContents[i], ...content};
142
- contentsSet(lContents);
143
- }
122
+ // Work on latest
123
+ contentsSet(l => arrayFindMerge(
124
+ l as contentStruct[], '_id', content._id, content, true
125
+ ) as contentStruct[]);
144
126
  }
145
127
 
146
128
  // Called to delete the template
@@ -158,7 +140,7 @@ export default function Template(props: TemplateProps) {
158
140
  editSet(false);
159
141
 
160
142
  // Let the parent know
161
- props.onChange(edit as templateStruct);
143
+ onChange(edit as templateStruct);
162
144
 
163
145
  }, (error: responseErrorStruct) => {
164
146
  if(error.code === errors.body.DB_DUPLICATE) {
@@ -176,7 +158,7 @@ export default function Template(props: TemplateProps) {
176
158
  } else {
177
159
  if(contents === false) {
178
160
  mouth.read('template/contents', {
179
- template: props.value._id
161
+ template: value._id
180
162
  }).then(contentsSet);
181
163
  }
182
164
  viewSet(true);
@@ -189,19 +171,19 @@ export default function Template(props: TemplateProps) {
189
171
  <Box className="flexColumns">
190
172
  <Box className="flexGrow link" onClick={viewToggle}>
191
173
  <h2>
192
- {ucfirst(props.value.name.replace(/_/g, ' '))}&nbsp;&nbsp;
174
+ {ucfirst(value.name.replace(/_/g, ' '))}&nbsp;&nbsp;
193
175
  <i className={'fa-solid fa-angle-' + (view ? 'up' : 'down')} />
194
176
  </h2>
195
177
  </Box>
196
178
  <Box className="flexStatic">
197
- {props.rights.template.update &&
179
+ {rights.template.update &&
198
180
  <Tooltip title="Edit the Template">
199
- <IconButton className="icon" onClick={ev => editSet(edit ? false : clone(props.value))}>
181
+ <IconButton className="icon" onClick={ev => editSet(edit ? false : { ...value })}>
200
182
  <i className={'fa-solid fa-edit ' + (edit ? 'open' : 'closed')} />
201
183
  </IconButton>
202
184
  </Tooltip>
203
185
  }
204
- {props.rights.template.delete &&
186
+ {rights.template.delete &&
205
187
  <Tooltip title="Delete the Template">
206
188
  <IconButton className="icon" onClick={remove}>
207
189
  <i className="fa-solid fa-trash-alt" />
@@ -221,7 +203,7 @@ export default function Template(props: TemplateProps) {
221
203
  label="none"
222
204
  name="name"
223
205
  node={oNameNode}
224
- onChange={value => change('name', value)}
206
+ onChange={val => change('name', val)}
225
207
  onEnterPressed={update}
226
208
  ref={refName}
227
209
  type="update"
@@ -231,7 +213,7 @@ export default function Template(props: TemplateProps) {
231
213
  <Grid item lg={6} md={12}>
232
214
  <Typography><strong>Variables</strong></Typography>
233
215
  <Variables
234
- onChange={value => change('variables', value)}
216
+ onChange={val => change('variables', val)}
235
217
  value={edit.variables || {}}
236
218
  />
237
219
  </Grid>
@@ -254,9 +236,9 @@ export default function Template(props: TemplateProps) {
254
236
  value={tab}
255
237
  >
256
238
  {contents && contents.map(o =>
257
- <Tab key={o._id} label={props.locales[o.locale] + ' ' + o.type} />
239
+ <Tab key={o._id} label={locales[o.locale] + ' ' + o.type} />
258
240
  )}
259
- {props.rights.content.create &&
241
+ {rights.content.create &&
260
242
  <Tab label={
261
243
  <i className="fa-solid fa-plus" />
262
244
  } />
@@ -265,37 +247,34 @@ export default function Template(props: TemplateProps) {
265
247
  <Box className="padding">
266
248
  <br />
267
249
  {(contents && tab < contents.length &&
268
- (props.rights.content.update ?
250
+ (rights.content.update ?
269
251
  <ContentUpdate
270
252
  key={contents[tab]._id}
271
- mobile={props.mobile}
272
- onError={props.onError}
253
+ onError={onError}
273
254
  onUpdated={contentUpdated}
274
255
  value={contents[tab]}
275
256
  />
276
257
  :
277
258
  <ContentView
278
259
  key={contents[tab]._id}
279
- mobile={props.mobile}
280
- onError={props.onError}
260
+ onError={onError}
281
261
  value={contents[tab]}
282
262
  />
283
263
  )
284
264
  ) ||
285
- ((props.rights.content.create && contents && tab === contents.length) &&
265
+ ((rights.content.create && contents && tab === contents.length) &&
286
266
  <ContentCreate
287
- locales={props.locales}
288
- mobile={props.mobile}
267
+ locales={locales}
289
268
  onCreated={contentCreated}
290
- onError={props.onError}
291
- template={props.value._id as string}
269
+ onError={onError}
270
+ template={value._id as string}
292
271
  />
293
272
  )}
294
273
  </Box>
295
274
  </Grid>
296
275
  <Grid item xs={12} md={3} xl={2}>
297
276
  <h4>Available Variables</h4>
298
- {props.value && omap(props.value.variables, (v,k) =>
277
+ {value && omap(value.variables, (v,k) =>
299
278
  <Typography key={k}>{'{' + k + '}'}</Typography>
300
279
  )}
301
280
  </Grid>
@@ -309,7 +288,6 @@ export default function Template(props: TemplateProps) {
309
288
  // Valid props
310
289
  Template.propTypes = {
311
290
  locales: PropTypes.objectOf(PropTypes.string).isRequired,
312
- mobile: PropTypes.bool.isRequired,
313
291
  onChange: PropTypes.func.isRequired,
314
292
  onError: PropTypes.func.isRequired,
315
293
  onContent: PropTypes.func.isRequired,
@@ -9,9 +9,8 @@
9
9
 
10
10
  // Ouroboros modules
11
11
  import { useRights } from '@ouroboros/brain-react';
12
- import clone from '@ouroboros/clone';
13
12
  import mouth from '@ouroboros/mouth';
14
- import { afindi } from '@ouroboros/tools';
13
+ import { arrayFindOverwrite } from '@ouroboros/tools';
15
14
 
16
15
  // NPM modules
17
16
  import PropTypes from 'prop-types';
@@ -29,7 +28,6 @@ import Template, { templateStruct } from './Template';
29
28
  // Types
30
29
  import { responseErrorStruct } from '@ouroboros/body';
31
30
  export type TemplatesProps = {
32
- mobile: boolean,
33
31
  onError: (error: responseErrorStruct) => void,
34
32
  onSuccess: (type: string) => void
35
33
  }
@@ -44,12 +42,12 @@ export type TemplatesProps = {
44
42
  * @param Object props Properties passed to the component
45
43
  * @returns React.Component
46
44
  */
47
- export default function Templates(props: TemplatesProps) {
45
+ export default function Templates({ onError, onSuccess }: TemplatesProps) {
48
46
 
49
47
  // State
50
- const [create, createSet] = useState<boolean>(false);
51
- const [locales, localesSet] = useState<Record<string, string>>({});
52
- const [templates, templatesSet] = useState<templateStruct[]>([]);
48
+ const [ create, createSet ] = useState<boolean>(false);
49
+ const [ locales, localesSet ] = useState<Record<string, string>>({ });
50
+ const [ templates, templatesSet ] = useState<templateStruct[]>([ ]);
53
51
 
54
52
  // Hooks
55
53
  const rightsContent = useRights('mouth_content');
@@ -78,42 +76,34 @@ export default function Templates(props: TemplatesProps) {
78
76
  createSet(false);
79
77
  }
80
78
 
81
- }, [rightsTemplate]);
79
+ }, [ rightsTemplate ]);
82
80
 
83
81
  // Called when a template has been created
84
82
  function templateCreated(template: templateStruct) {
85
83
 
86
84
  // Notify parent
87
- props.onSuccess('template_create');
85
+ onSuccess('template_create');
88
86
 
89
87
  // Hide the create form
90
88
  createSet(false);
91
89
 
92
90
  // Clone the current templates, add the new one to the front, and set
93
91
  // the new templates
94
- const lTemplates = clone(templates);
95
- lTemplates.unshift(template);
96
- templatesSet(lTemplates);
92
+ templatesSet(l => [ template, ...l ])
97
93
  }
98
94
 
99
95
  // Called when a template has been updated
100
96
  function templateUpdated(template: templateStruct) {
101
97
 
102
98
  // Notify parent
103
- props.onSuccess('template_update');
104
-
105
- // Look for the template
106
- const i = afindi(templates, '_id', template._id);
107
-
108
- // If we have it
109
- if(i > -1) {
110
-
111
- // Clone the current templates, update the index, and set the new
112
- // templates
113
- const lTemplates = clone(templates);
114
- lTemplates[i] = template;
115
- templatesSet(lTemplates);
116
- }
99
+ onSuccess('template_update');
100
+
101
+ // Work on latest
102
+ templatesSet(l =>
103
+ arrayFindOverwrite(
104
+ l, '_id', template._id, template, true
105
+ ) as templateStruct[]
106
+ );
117
107
  }
118
108
 
119
109
  // Render
@@ -135,17 +125,16 @@ export default function Templates(props: TemplatesProps) {
135
125
  <Create
136
126
  onCancel={() => createSet(false)}
137
127
  onCreated={templateCreated}
138
- onError={props.onError}
128
+ onError={onError}
139
129
  />
140
130
  }
141
131
  {templates.map((o: templateStruct) =>
142
132
  <Template
143
133
  key={o._id}
144
134
  locales={locales}
145
- mobile={props.mobile}
146
135
  onChange={templateUpdated}
147
- onContent={type => props.onSuccess(`content_${type}`)}
148
- onError={props.onError}
136
+ onContent={type => onSuccess(`content_${type}`)}
137
+ onError={onError}
149
138
  rights={{
150
139
  content: rightsContent,
151
140
  template: rightsTemplate
@@ -159,7 +148,6 @@ export default function Templates(props: TemplatesProps) {
159
148
 
160
149
  // Valid props
161
150
  Templates.propTypes = {
162
- mobile: PropTypes.bool.isRequired,
163
151
  onError: PropTypes.func.isRequired,
164
152
  onSuccess: PropTypes.func.isRequired
165
153
  }
package/src/shared.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared
3
+ *
4
+ * Holds the Trees used by all the components
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @copyright Ouroboros Coding Inc.
8
+ * @created 2025-03-11
9
+ */
10
+
11
+ // Ouroboros imports
12
+ import { Tree } from '@ouroboros/define';
13
+
14
+ // Mouth definition files
15
+ import TemplateEmailDef from '@ouroboros/mouth/define/template_email.json';
16
+ import TemplateSMSDef from '@ouroboros/mouth/define/template_sms.json';
17
+
18
+ // Generate the email Tree
19
+ export const EmailTree = new Tree(TemplateEmailDef, {
20
+ __name__: 'record',
21
+ text: { __ui__: { __title__: 'Plain Text', __type__: 'textarea' } },
22
+ html: { __ui__: { __title__: 'Raw HTML', __type__: 'textarea' } }
23
+ });
24
+
25
+ // Generate the sms Tree
26
+ export const SmsTree = new Tree(TemplateSMSDef, {
27
+ __name__: 'record',
28
+ content: { __ui__: { __title__: 'Content', __type__: 'textarea' } }
29
+ });
Binary file
@@ -1,3 +0,0 @@
1
- declare module "xhr2" {
2
- export default XMLHttpRequest;
3
- }