@ouroboros/mouth-mui 1.0.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 (60) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +15 -0
  3. package/package.json +55 -0
  4. package/src/components/pages/Locales.d.ts +35 -0
  5. package/src/components/pages/Locales.js +188 -0
  6. package/src/components/pages/Locales.tsx +254 -0
  7. package/src/components/pages/Templates/Create.d.ts +36 -0
  8. package/src/components/pages/Templates/Create.js +98 -0
  9. package/src/components/pages/Templates/Create.tsx +139 -0
  10. package/src/components/pages/Templates/Template/Content/Create/Email.d.ts +39 -0
  11. package/src/components/pages/Templates/Template/Content/Create/Email.js +51 -0
  12. package/src/components/pages/Templates/Template/Content/Create/Email.tsx +96 -0
  13. package/src/components/pages/Templates/Template/Content/Create/SMS.d.ts +37 -0
  14. package/src/components/pages/Templates/Template/Content/Create/SMS.js +42 -0
  15. package/src/components/pages/Templates/Template/Content/Create/SMS.tsx +68 -0
  16. package/src/components/pages/Templates/Template/Content/Create/index.d.ts +42 -0
  17. package/src/components/pages/Templates/Template/Content/Create/index.js +177 -0
  18. package/src/components/pages/Templates/Template/Content/Create/index.tsx +257 -0
  19. package/src/components/pages/Templates/Template/Content/Preview/Email.d.ts +37 -0
  20. package/src/components/pages/Templates/Template/Content/Preview/Email.js +51 -0
  21. package/src/components/pages/Templates/Template/Content/Preview/Email.tsx +78 -0
  22. package/src/components/pages/Templates/Template/Content/Preview/SMS.d.ts +32 -0
  23. package/src/components/pages/Templates/Template/Content/Preview/SMS.js +38 -0
  24. package/src/components/pages/Templates/Template/Content/Preview/SMS.tsx +59 -0
  25. package/src/components/pages/Templates/Template/Content/Preview/index.d.ts +42 -0
  26. package/src/components/pages/Templates/Template/Content/Preview/index.js +63 -0
  27. package/src/components/pages/Templates/Template/Content/Preview/index.tsx +107 -0
  28. package/src/components/pages/Templates/Template/Content/Update/Email.d.ts +39 -0
  29. package/src/components/pages/Templates/Template/Content/Update/Email.js +51 -0
  30. package/src/components/pages/Templates/Template/Content/Update/Email.tsx +96 -0
  31. package/src/components/pages/Templates/Template/Content/Update/SMS.d.ts +37 -0
  32. package/src/components/pages/Templates/Template/Content/Update/SMS.js +42 -0
  33. package/src/components/pages/Templates/Template/Content/Update/SMS.tsx +68 -0
  34. package/src/components/pages/Templates/Template/Content/Update/index.d.ts +42 -0
  35. package/src/components/pages/Templates/Template/Content/Update/index.js +117 -0
  36. package/src/components/pages/Templates/Template/Content/Update/index.tsx +162 -0
  37. package/src/components/pages/Templates/Template/Content/View/Email.d.ts +43 -0
  38. package/src/components/pages/Templates/Template/Content/View/Email.js +57 -0
  39. package/src/components/pages/Templates/Template/Content/View/Email.tsx +80 -0
  40. package/src/components/pages/Templates/Template/Content/View/SMS.d.ts +41 -0
  41. package/src/components/pages/Templates/Template/Content/View/SMS.js +46 -0
  42. package/src/components/pages/Templates/Template/Content/View/SMS.tsx +64 -0
  43. package/src/components/pages/Templates/Template/Content/View/index.d.ts +39 -0
  44. package/src/components/pages/Templates/Template/Content/View/index.js +50 -0
  45. package/src/components/pages/Templates/Template/Content/View/index.tsx +78 -0
  46. package/src/components/pages/Templates/Template/Variables.d.ts +34 -0
  47. package/src/components/pages/Templates/Template/Variables.js +91 -0
  48. package/src/components/pages/Templates/Template/Variables.tsx +138 -0
  49. package/src/components/pages/Templates/Template/index.d.ts +90 -0
  50. package/src/components/pages/Templates/Template/index.js +207 -0
  51. package/src/components/pages/Templates/Template/index.tsx +337 -0
  52. package/src/components/pages/Templates/index.d.ts +35 -0
  53. package/src/components/pages/Templates/index.js +112 -0
  54. package/src/components/pages/Templates/index.tsx +165 -0
  55. package/src/index.d.ts +5 -0
  56. package/src/index.js +5 -0
  57. package/src/index.ts +8 -0
  58. package/src/locales.d.ts +72 -0
  59. package/src/locales.js +160 -0
  60. package/src/locales.ts +200 -0
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Ouroboros Coding Inc. License
2
+
3
+ Copyright (c) 2023 Ouroboros Coding Inc.
4
+
5
+ Permission is hereby granted, with limits, to any person using this software
6
+ within a project created by Ouroboros Coding Inc. Any attempt to modify this
7
+ code, or use it outside projects created by Ouroboros Coding Inc, will result
8
+ in legal action taken against the party using the code.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @ouroboros/mouth-mui
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ouroboros/mouth-mui.svg)](https://www.npmjs.com/package/@ouroboros/mouth-mui)
4
+
5
+ Shared Material-UI Components for interacting with the mouth service created by
6
+ Ouroboros Coding Inc.
7
+
8
+ This code comes without documentation as it's not meant to be used by anyone
9
+ outside of Ouroboros Coding Inc. Please see LICENSE for further information.
10
+
11
+ ## Installation
12
+ npm
13
+ ```bash
14
+ npm install @ouroboros/mouth-mui
15
+ ```
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@ouroboros/mouth-mui",
3
+ "version": "1.0.0",
4
+ "description": "Components for use with the Mouth service",
5
+ "main": "src/index.js",
6
+ "types": "src/index.d.ts",
7
+ "scripts": {
8
+ "build": "tslint -p tsconfig.json && tsc",
9
+ "clean": "cd src; find . -type f -name \"*.js\" -delete; find . -type f -name \"*.d.ts\" -delete",
10
+ "for_local": "npm install; tslint -p tsconfig.json && tsc; rm -Rf node_modules",
11
+ "test": "echo \"Error: no test specified.\" && exit 1"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/ouroboroscoding/mouth-mui.git"
16
+ },
17
+ "keywords": [
18
+ "@ouroboros/mouth",
19
+ "material-ui",
20
+ "mui",
21
+ "react"
22
+ ],
23
+ "author": "Chris Nasr <chris@ouroboroscoding.com>",
24
+ "license": "CUSTOM",
25
+ "bugs": {
26
+ "url": "https://github.com/ouroboroscoding/mouth-mui/issues"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^18.14.0",
30
+ "@types/react": "^18.0.28",
31
+ "@types/uuid": "^9.0.0",
32
+ "tslint": "^6.1.3",
33
+ "tslint-config-prettier": "^1.18.0",
34
+ "typescript": "^4.8.3"
35
+ },
36
+ "dependencies": {
37
+ "@ouroboros/clone": "^1.0.1",
38
+ "@ouroboros/define": "^1.0.2",
39
+ "@ouroboros/define-mui": "^1.0.3",
40
+ "@ouroboros/react-radiobuttons-mui": "^1.0.0",
41
+ "@ouroboros/subscribe": "^1.2.0",
42
+ "@ouroboros/tools": "^0.4.1",
43
+ "prop-types": "^15.8.1"
44
+ },
45
+ "peerDependencies": {
46
+ "@emotion/react": "^11.8.2",
47
+ "@emotion/styled": "^11.8.1",
48
+ "@mui/material": "^5.5.1",
49
+ "@ouroboros/body": "^1.0.0",
50
+ "@ouroboros/brain-mui": "^1.0.0",
51
+ "@ouroboros/mouth": "^1.0.0",
52
+ "react": "^17.0.2",
53
+ "react-dom": "^17.0.2"
54
+ }
55
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Communications Locales
3
+ *
4
+ * Locales page
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @created 2023-01-19
8
+ */
9
+ /// <reference types="react" />
10
+ import PropTypes from 'prop-types';
11
+ import { responseErrorStruct } from '@ouroboros/body';
12
+ export type LocalesProps = {
13
+ mobile: boolean;
14
+ onError: (error: responseErrorStruct) => void;
15
+ onSuccess: (type: string) => void;
16
+ };
17
+ /**
18
+ * Locales
19
+ *
20
+ * Handles template locale management
21
+ *
22
+ * @name Locales
23
+ * @access public
24
+ * @param Object props Properties passed to the component
25
+ * @returns React.Component
26
+ */
27
+ declare function Locales(props: LocalesProps): JSX.Element;
28
+ declare namespace Locales {
29
+ var propTypes: {
30
+ mobile: PropTypes.Validator<boolean>;
31
+ onError: PropTypes.Validator<(...args: any[]) => any>;
32
+ onSuccess: PropTypes.Validator<(...args: any[]) => any>;
33
+ };
34
+ }
35
+ export default Locales;
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Communications Locales
3
+ *
4
+ * Locales page
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @created 2023-01-19
8
+ */
9
+ // Ouroboros modules
10
+ import { Myself } from '@ouroboros/brain-mui';
11
+ import clone from '@ouroboros/clone';
12
+ import { Tree } from '@ouroboros/define';
13
+ import { Form, Results } from '@ouroboros/define-mui';
14
+ import mouth, { errors } from '@ouroboros/mouth';
15
+ import LocaleDef from '@ouroboros/mouth/definitions/locale.json';
16
+ import { afindi, merge } from '@ouroboros/tools';
17
+ // NPM modules
18
+ import PropTypes from 'prop-types';
19
+ import React, { useEffect, useState } from 'react';
20
+ // Material UI
21
+ import Box from '@mui/material/Box';
22
+ import IconButton from '@mui/material/IconButton';
23
+ import Paper from '@mui/material/Paper';
24
+ import Tooltip from '@mui/material/Tooltip';
25
+ // Local modules
26
+ import locales from '../../locales';
27
+ // Generate the user Tree
28
+ const LocaleTree = new Tree(LocaleDef);
29
+ /**
30
+ * Locales
31
+ *
32
+ * Handles template locale management
33
+ *
34
+ * @name Locales
35
+ * @access public
36
+ * @param Object props Properties passed to the component
37
+ * @returns React.Component
38
+ */
39
+ export default function Locales(props) {
40
+ // State
41
+ const [create, createSet] = useState(false);
42
+ const [records, recordsSet] = useState([]);
43
+ // Hooks
44
+ const rights = Myself.useRights('mouth_locale');
45
+ // User / archived change effect
46
+ useEffect(() => {
47
+ // If we have read rights
48
+ if (rights.read) {
49
+ mouth.read('locale').then(recordsSet);
50
+ }
51
+ else {
52
+ recordsSet([]);
53
+ }
54
+ // If we don't have create rights
55
+ if (!rights.create) {
56
+ createSet(false);
57
+ }
58
+ }, [rights]);
59
+ // Called when a create form is submitted
60
+ function createSubmit(locale) {
61
+ // Create a new Promise and return it
62
+ return new Promise((resolve, reject) => {
63
+ // Create the new locale
64
+ mouth.create('locale').then((data) => {
65
+ // If we were successful
66
+ if (data) {
67
+ // Notify the parent
68
+ props.onSuccess('create');
69
+ // Close the create form
70
+ createSet(false);
71
+ // Clone the records, add the new one to the start, and set the new
72
+ // records
73
+ const lRecords = clone(records);
74
+ lRecords.unshift(locale);
75
+ recordsSet(lRecords);
76
+ // Send the clone to the locales
77
+ locales.set(lRecords);
78
+ }
79
+ // Resolve with the form
80
+ resolve(data ? true : false);
81
+ }, (error) => {
82
+ if (error.code === errors.body.DB_NO_RECORD) {
83
+ reject([['_id', 'Already in use']]);
84
+ }
85
+ else if (error.code === errors.body.DATA_FIELDS) {
86
+ reject(error.msg);
87
+ }
88
+ else {
89
+ if (props.onError) {
90
+ props.onError(error);
91
+ }
92
+ else {
93
+ throw new Error(JSON.stringify(error));
94
+ }
95
+ }
96
+ });
97
+ });
98
+ }
99
+ // Called when the delete button on a locale was clicked
100
+ function deleteClick(key) {
101
+ // Delete the existing locale
102
+ mouth.delete('locale', { _id: key }).then((data) => {
103
+ // If it was successful
104
+ if (data) {
105
+ // Notify the parent
106
+ props.onSuccess('delete');
107
+ // Look for the record
108
+ const i = afindi(records, '_id', key);
109
+ // If it exists
110
+ if (i > -1) {
111
+ // Clone the records, delete the index, and set the new records
112
+ const lRecords = clone(records);
113
+ lRecords.splice(i, 1);
114
+ recordsSet(lRecords);
115
+ // Send the clone to the locales
116
+ locales.set(lRecords);
117
+ }
118
+ }
119
+ }, (error) => {
120
+ if (props.onError) {
121
+ props.onError(error);
122
+ }
123
+ else {
124
+ throw new Error(JSON.stringify(error));
125
+ }
126
+ });
127
+ }
128
+ // Called when an update form is submitted
129
+ function updateSubmit(locale, key) {
130
+ // Add the ID to the locale
131
+ locale._id = key;
132
+ // Create a new Promise and return it
133
+ return new Promise((resolve, reject) => {
134
+ // Update the locale on the server
135
+ mouth.update('locale', locale).then((data) => {
136
+ // If we were successful
137
+ if (data) {
138
+ // Notify the parent
139
+ props.onSuccess('update');
140
+ // Look for the record
141
+ const i = afindi(records, '_id', key);
142
+ // If it exists
143
+ if (i > -1) {
144
+ // Clone the records, update the index, and set the new records
145
+ const lRecords = clone(records);
146
+ merge(lRecords[i], locale);
147
+ recordsSet(lRecords);
148
+ // Send the clone to the locales
149
+ locales.set(lRecords);
150
+ }
151
+ }
152
+ // Resolve with the Form
153
+ resolve(data);
154
+ }, (error) => {
155
+ if (error.code === errors.body.DATA_FIELDS) {
156
+ reject(error.msg);
157
+ }
158
+ else {
159
+ if (props.onError) {
160
+ props.onError(error);
161
+ }
162
+ else {
163
+ throw new Error(JSON.stringify(error));
164
+ }
165
+ }
166
+ });
167
+ });
168
+ }
169
+ // Render
170
+ return (React.createElement(Box, { id: "mouth_locales", className: "flexGrow padding" },
171
+ React.createElement(Box, { className: "flexColumns" },
172
+ React.createElement("h1", { className: "flexGrow" }, "Locales"),
173
+ rights.create &&
174
+ React.createElement(Box, { className: "flexStatic" },
175
+ React.createElement(Tooltip, { title: "Create new Locale", className: "page_action", onClick: () => createSet(b => !b) },
176
+ React.createElement(IconButton, null,
177
+ React.createElement("i", { className: 'fa-solid fa-plus' + (create ? ' open' : '') }))))),
178
+ create &&
179
+ React.createElement(Paper, { className: "padding" },
180
+ React.createElement(Form, { onCancel: () => createSet(false), onSubmit: createSubmit, tree: LocaleTree, type: "create" })),
181
+ React.createElement(Results, { data: records, orderBy: "name", onDelete: rights.delete ? deleteClick : false, onUpdate: rights.update ? updateSubmit : false, tree: LocaleTree })));
182
+ }
183
+ // Valid props
184
+ Locales.propTypes = {
185
+ mobile: PropTypes.bool.isRequired,
186
+ onError: PropTypes.func.isRequired,
187
+ onSuccess: PropTypes.func.isRequired
188
+ };
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Communications Locales
3
+ *
4
+ * Locales page
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @created 2023-01-19
8
+ */
9
+
10
+ // Ouroboros modules
11
+ import { Myself } from '@ouroboros/brain-mui';
12
+ import clone from '@ouroboros/clone';
13
+ import { Tree } from '@ouroboros/define'
14
+ import { Form, Results } from '@ouroboros/define-mui';
15
+ import mouth, { errors } from '@ouroboros/mouth';
16
+ import LocaleDef from '@ouroboros/mouth/definitions/locale.json';
17
+ import { afindi, merge } from '@ouroboros/tools';
18
+
19
+ // NPM modules
20
+ import PropTypes from 'prop-types';
21
+ import React, { useEffect, useState } from 'react';
22
+
23
+ // Material UI
24
+ import Box from '@mui/material/Box';
25
+ import IconButton from '@mui/material/IconButton';
26
+ import Paper from '@mui/material/Paper';
27
+ import Tooltip from '@mui/material/Tooltip';
28
+
29
+ // Local modules
30
+ import locales from '../../locales';
31
+
32
+ // Generate the user Tree
33
+ const LocaleTree = new Tree(LocaleDef);
34
+
35
+ // Types
36
+ import { responseErrorStruct } from '@ouroboros/body';
37
+ export type LocalesProps = {
38
+ mobile: boolean,
39
+ onError: (error: responseErrorStruct) => void,
40
+ onSuccess: (type: string) => void
41
+ }
42
+
43
+ /**
44
+ * Locales
45
+ *
46
+ * Handles template locale management
47
+ *
48
+ * @name Locales
49
+ * @access public
50
+ * @param Object props Properties passed to the component
51
+ * @returns React.Component
52
+ */
53
+ export default function Locales(props: LocalesProps) {
54
+
55
+ // State
56
+ const [create, createSet] = useState<boolean>(false);
57
+ const [records, recordsSet] = useState<any[]>([]);
58
+
59
+ // Hooks
60
+ const rights = Myself.useRights('mouth_locale');
61
+
62
+ // User / archived change effect
63
+ useEffect(() => {
64
+
65
+ // If we have read rights
66
+ if(rights.read) {
67
+ mouth.read('locale').then(recordsSet);
68
+ } else {
69
+ recordsSet([]);
70
+ }
71
+
72
+ // If we don't have create rights
73
+ if(!rights.create) {
74
+ createSet(false);
75
+ }
76
+
77
+ }, [rights]);
78
+
79
+ // Called when a create form is submitted
80
+ function createSubmit(locale: any): Promise<boolean> {
81
+
82
+ // Create a new Promise and return it
83
+ return new Promise((resolve, reject) => {
84
+
85
+ // Create the new locale
86
+ mouth.create('locale').then((data: string) => {
87
+
88
+ // If we were successful
89
+ if(data) {
90
+
91
+ // Notify the parent
92
+ props.onSuccess('create');
93
+
94
+ // Close the create form
95
+ createSet(false);
96
+
97
+ // Clone the records, add the new one to the start, and set the new
98
+ // records
99
+ const lRecords = clone(records);
100
+ lRecords.unshift(locale);
101
+ recordsSet(lRecords);
102
+
103
+ // Send the clone to the locales
104
+ locales.set(lRecords);
105
+ }
106
+
107
+ // Resolve with the form
108
+ resolve(data ? true : false);
109
+
110
+ }, (error: responseErrorStruct) => {
111
+ if(error.code === errors.body.DB_NO_RECORD) {
112
+ reject([['_id', 'Already in use']]);
113
+ } else if(error.code === errors.body.DATA_FIELDS) {
114
+ reject(error.msg);
115
+ } else {
116
+ if(props.onError) {
117
+ props.onError(error);
118
+ } else {
119
+ throw new Error(JSON.stringify(error));
120
+ }
121
+ }
122
+ });
123
+ });
124
+ }
125
+
126
+ // Called when the delete button on a locale was clicked
127
+ function deleteClick(key: string) {
128
+
129
+ // Delete the existing locale
130
+ mouth.delete('locale', { _id: key }).then((data: boolean) => {
131
+
132
+ // If it was successful
133
+ if(data) {
134
+
135
+ // Notify the parent
136
+ props.onSuccess('delete');
137
+
138
+ // Look for the record
139
+ const i = afindi(records, '_id', key);
140
+
141
+ // If it exists
142
+ if(i > -1) {
143
+
144
+ // Clone the records, delete the index, and set the new records
145
+ const lRecords = clone(records);
146
+ lRecords.splice(i, 1);
147
+ recordsSet(lRecords);
148
+
149
+ // Send the clone to the locales
150
+ locales.set(lRecords);
151
+ }
152
+ }
153
+ }, (error: responseErrorStruct) => {
154
+ if(props.onError) {
155
+ props.onError(error);
156
+ } else {
157
+ throw new Error(JSON.stringify(error));
158
+ }
159
+ });
160
+ }
161
+
162
+ // Called when an update form is submitted
163
+ function updateSubmit(locale: any, key: string): Promise<boolean> {
164
+
165
+ // Add the ID to the locale
166
+ locale._id = key;
167
+
168
+ // Create a new Promise and return it
169
+ return new Promise((resolve, reject) => {
170
+
171
+ // Update the locale on the server
172
+ mouth.update('locale', locale).then((data: boolean) => {
173
+
174
+ // If we were successful
175
+ if(data) {
176
+
177
+ // Notify the parent
178
+ props.onSuccess('update');
179
+
180
+ // Look for the record
181
+ const i = afindi(records, '_id', key);
182
+
183
+ // If it exists
184
+ if(i > -1) {
185
+
186
+ // Clone the records, update the index, and set the new records
187
+ const lRecords = clone(records);
188
+ merge(lRecords[i], locale);
189
+ recordsSet(lRecords);
190
+
191
+ // Send the clone to the locales
192
+ locales.set(lRecords);
193
+ }
194
+ }
195
+
196
+ // Resolve with the Form
197
+ resolve(data);
198
+
199
+ }, (error: responseErrorStruct) => {
200
+ if(error.code === errors.body.DATA_FIELDS) {
201
+ reject(error.msg);
202
+ } else {
203
+ if(props.onError) {
204
+ props.onError(error);
205
+ } else {
206
+ throw new Error(JSON.stringify(error));
207
+ }
208
+ }
209
+ });
210
+ });
211
+ }
212
+
213
+ // Render
214
+ return (
215
+ <Box id="mouth_locales" className="flexGrow padding">
216
+ <Box className="flexColumns">
217
+ <h1 className="flexGrow">Locales</h1>
218
+ {rights.create &&
219
+ <Box className="flexStatic">
220
+ <Tooltip title="Create new Locale" className="page_action" onClick={() => createSet(b => !b)}>
221
+ <IconButton>
222
+ <i className={'fa-solid fa-plus' + (create ? ' open' : '')} />
223
+ </IconButton>
224
+ </Tooltip>
225
+ </Box>
226
+ }
227
+ </Box>
228
+ {create &&
229
+ <Paper className="padding">
230
+ <Form
231
+ onCancel={() => createSet(false)}
232
+ onSubmit={createSubmit}
233
+ tree={LocaleTree}
234
+ type="create"
235
+ />
236
+ </Paper>
237
+ }
238
+ <Results
239
+ data={records}
240
+ orderBy="name"
241
+ onDelete={rights.delete ? deleteClick : false}
242
+ onUpdate={rights.update ? updateSubmit : false}
243
+ tree={LocaleTree}
244
+ />
245
+ </Box>
246
+ );
247
+ }
248
+
249
+ // Valid props
250
+ Locales.propTypes = {
251
+ mobile: PropTypes.bool.isRequired,
252
+ onError: PropTypes.func.isRequired,
253
+ onSuccess: PropTypes.func.isRequired
254
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Templates Create
3
+ *
4
+ * Create component
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @created 2023-01-20
8
+ */
9
+ /// <reference types="react" />
10
+ import PropTypes from 'prop-types';
11
+ import { responseErrorStruct } from '@ouroboros/body';
12
+ import { templateStruct } from './Template';
13
+ export interface CreateProps {
14
+ onCancel?: () => void;
15
+ onCreated: (template: templateStruct) => void;
16
+ onError: (error: responseErrorStruct) => void;
17
+ }
18
+ /**
19
+ * Create
20
+ *
21
+ * Form for creating a new template
22
+ *
23
+ * @name Create
24
+ * @access public
25
+ * @param Object props Properties passed to the component
26
+ * @returns React.Component
27
+ */
28
+ declare function Create(props: CreateProps): JSX.Element;
29
+ declare namespace Create {
30
+ var propTypes: {
31
+ onCancel: PropTypes.Requireable<(...args: any[]) => any>;
32
+ onCreated: PropTypes.Validator<(...args: any[]) => any>;
33
+ onError: PropTypes.Validator<(...args: any[]) => any>;
34
+ };
35
+ }
36
+ export default Create;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Templates Create
3
+ *
4
+ * Create component
5
+ *
6
+ * @author Chris Nasr <chris@ouroboroscoding.com>
7
+ * @created 2023-01-20
8
+ */
9
+ // Ouroboros modules
10
+ import clone from '@ouroboros/clone';
11
+ import { Node } from '@ouroboros/define';
12
+ import { DefineNode } from '@ouroboros/define-mui';
13
+ import mouth, { errors } from '@ouroboros/mouth';
14
+ import TemplateDef from '@ouroboros/mouth/definitions/template.json';
15
+ // NPM modules
16
+ import PropTypes from 'prop-types';
17
+ import React, { useRef, useState } from 'react';
18
+ // Material UI
19
+ import Button from '@mui/material/Button';
20
+ import Grid from '@mui/material/Grid';
21
+ import Paper from '@mui/material/Paper';
22
+ import Typography from '@mui/material/Typography';
23
+ // Locale components
24
+ import Variables from './Template/Variables';
25
+ // Format Node
26
+ const oNameNode = new Node(TemplateDef.name);
27
+ /**
28
+ * Create
29
+ *
30
+ * Form for creating a new template
31
+ *
32
+ * @name Create
33
+ * @access public
34
+ * @param Object props Properties passed to the component
35
+ * @returns React.Component
36
+ */
37
+ export default function Create(props) {
38
+ // State
39
+ const [record, recordSet] = useState({
40
+ name: '',
41
+ variables: {}
42
+ });
43
+ // Refs
44
+ const refName = useRef(null);
45
+ // Called when record changes
46
+ function change(field, value) {
47
+ // Set the new record
48
+ recordSet(o => {
49
+ const oRecord = clone(o);
50
+ oRecord[field] = value;
51
+ return oRecord;
52
+ });
53
+ }
54
+ // Called to create the template
55
+ function create() {
56
+ // Create the data in the system
57
+ mouth.create('template', record).then(data => {
58
+ // Add the ID to the record
59
+ record._id = data;
60
+ // Let the parent know
61
+ props.onCreated(clone(record));
62
+ }, error => {
63
+ if (error.code === errors.body.DB_DUPLICATE) {
64
+ refName.current?.error('Duplicate');
65
+ }
66
+ else {
67
+ if (props.onError) {
68
+ props.onError(error);
69
+ }
70
+ else {
71
+ throw new Error(JSON.stringify(error));
72
+ }
73
+ }
74
+ });
75
+ }
76
+ // Render
77
+ return (React.createElement(Paper, { className: "padding" },
78
+ React.createElement("h2", null, "Create new Template"),
79
+ React.createElement(Grid, { container: true, spacing: 2 },
80
+ React.createElement(Grid, { item: true, lg: 6, md: 12, className: "field" },
81
+ React.createElement(Typography, null,
82
+ React.createElement("strong", null, "Name")),
83
+ React.createElement(DefineNode, { label: "none", name: "name", node: oNameNode, onChange: value => change('name', value), onEnterPressed: create, ref: refName, type: "create", value: record.name || null })),
84
+ React.createElement(Grid, { item: true, lg: 6, md: 12 },
85
+ React.createElement(Typography, null,
86
+ React.createElement("strong", null, "Variables")),
87
+ React.createElement(Variables, { onChange: value => change('variables', value), value: record.variables || {} })),
88
+ React.createElement(Grid, { item: true, xs: 12, className: "actions" },
89
+ props.onCancel &&
90
+ React.createElement(Button, { variant: "contained", color: "secondary", onClick: props.onCancel }, "Cancel"),
91
+ React.createElement(Button, { variant: "contained", color: "primary", onClick: create }, "Create Template")))));
92
+ }
93
+ // Valid props
94
+ Create.propTypes = {
95
+ onCancel: PropTypes.func,
96
+ onCreated: PropTypes.func.isRequired,
97
+ onError: PropTypes.func.isRequired,
98
+ };