@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.
- package/LICENSE +8 -0
- package/README.md +15 -0
- package/package.json +55 -0
- package/src/components/pages/Locales.d.ts +35 -0
- package/src/components/pages/Locales.js +188 -0
- package/src/components/pages/Locales.tsx +254 -0
- package/src/components/pages/Templates/Create.d.ts +36 -0
- package/src/components/pages/Templates/Create.js +98 -0
- package/src/components/pages/Templates/Create.tsx +139 -0
- package/src/components/pages/Templates/Template/Content/Create/Email.d.ts +39 -0
- package/src/components/pages/Templates/Template/Content/Create/Email.js +51 -0
- package/src/components/pages/Templates/Template/Content/Create/Email.tsx +96 -0
- package/src/components/pages/Templates/Template/Content/Create/SMS.d.ts +37 -0
- package/src/components/pages/Templates/Template/Content/Create/SMS.js +42 -0
- package/src/components/pages/Templates/Template/Content/Create/SMS.tsx +68 -0
- package/src/components/pages/Templates/Template/Content/Create/index.d.ts +42 -0
- package/src/components/pages/Templates/Template/Content/Create/index.js +177 -0
- package/src/components/pages/Templates/Template/Content/Create/index.tsx +257 -0
- package/src/components/pages/Templates/Template/Content/Preview/Email.d.ts +37 -0
- package/src/components/pages/Templates/Template/Content/Preview/Email.js +51 -0
- package/src/components/pages/Templates/Template/Content/Preview/Email.tsx +78 -0
- package/src/components/pages/Templates/Template/Content/Preview/SMS.d.ts +32 -0
- package/src/components/pages/Templates/Template/Content/Preview/SMS.js +38 -0
- package/src/components/pages/Templates/Template/Content/Preview/SMS.tsx +59 -0
- package/src/components/pages/Templates/Template/Content/Preview/index.d.ts +42 -0
- package/src/components/pages/Templates/Template/Content/Preview/index.js +63 -0
- package/src/components/pages/Templates/Template/Content/Preview/index.tsx +107 -0
- package/src/components/pages/Templates/Template/Content/Update/Email.d.ts +39 -0
- package/src/components/pages/Templates/Template/Content/Update/Email.js +51 -0
- package/src/components/pages/Templates/Template/Content/Update/Email.tsx +96 -0
- package/src/components/pages/Templates/Template/Content/Update/SMS.d.ts +37 -0
- package/src/components/pages/Templates/Template/Content/Update/SMS.js +42 -0
- package/src/components/pages/Templates/Template/Content/Update/SMS.tsx +68 -0
- package/src/components/pages/Templates/Template/Content/Update/index.d.ts +42 -0
- package/src/components/pages/Templates/Template/Content/Update/index.js +117 -0
- package/src/components/pages/Templates/Template/Content/Update/index.tsx +162 -0
- package/src/components/pages/Templates/Template/Content/View/Email.d.ts +43 -0
- package/src/components/pages/Templates/Template/Content/View/Email.js +57 -0
- package/src/components/pages/Templates/Template/Content/View/Email.tsx +80 -0
- package/src/components/pages/Templates/Template/Content/View/SMS.d.ts +41 -0
- package/src/components/pages/Templates/Template/Content/View/SMS.js +46 -0
- package/src/components/pages/Templates/Template/Content/View/SMS.tsx +64 -0
- package/src/components/pages/Templates/Template/Content/View/index.d.ts +39 -0
- package/src/components/pages/Templates/Template/Content/View/index.js +50 -0
- package/src/components/pages/Templates/Template/Content/View/index.tsx +78 -0
- package/src/components/pages/Templates/Template/Variables.d.ts +34 -0
- package/src/components/pages/Templates/Template/Variables.js +91 -0
- package/src/components/pages/Templates/Template/Variables.tsx +138 -0
- package/src/components/pages/Templates/Template/index.d.ts +90 -0
- package/src/components/pages/Templates/Template/index.js +207 -0
- package/src/components/pages/Templates/Template/index.tsx +337 -0
- package/src/components/pages/Templates/index.d.ts +35 -0
- package/src/components/pages/Templates/index.js +112 -0
- package/src/components/pages/Templates/index.tsx +165 -0
- package/src/index.d.ts +5 -0
- package/src/index.js +5 -0
- package/src/index.ts +8 -0
- package/src/locales.d.ts +72 -0
- package/src/locales.js +160 -0
- package/src/locales.ts +200 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Communications Templates Variables
|
|
3
|
+
*
|
|
4
|
+
* Variables 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 { omap } from '@ouroboros/tools';
|
|
14
|
+
// NPM modules
|
|
15
|
+
import PropTypes from 'prop-types';
|
|
16
|
+
import React, { useRef } from 'react';
|
|
17
|
+
// Material UI
|
|
18
|
+
import Box from '@mui/material/Box';
|
|
19
|
+
import Grid from '@mui/material/Grid';
|
|
20
|
+
import IconButton from '@mui/material/IconButton';
|
|
21
|
+
import TextField from '@mui/material/TextField';
|
|
22
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
23
|
+
// Create hash node
|
|
24
|
+
const oNameNode = new Node({
|
|
25
|
+
__type__: 'string',
|
|
26
|
+
__regex__: '^[a-z_]+$'
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Variables
|
|
30
|
+
*
|
|
31
|
+
* Handles template locale management
|
|
32
|
+
*
|
|
33
|
+
* @name Variables
|
|
34
|
+
* @access public
|
|
35
|
+
* @param Object props Properties passed to the component
|
|
36
|
+
* @returns React.Component
|
|
37
|
+
*/
|
|
38
|
+
export default function Variables(props) {
|
|
39
|
+
// Refs
|
|
40
|
+
const refName = useRef(null);
|
|
41
|
+
const refValue = useRef(null);
|
|
42
|
+
// Called when a new variable is added
|
|
43
|
+
function add() {
|
|
44
|
+
// Clone the current value
|
|
45
|
+
const oValue = clone(props.value);
|
|
46
|
+
// If we have references to the inputs
|
|
47
|
+
if (refName.current && refValue.current) {
|
|
48
|
+
// Add the new item to it
|
|
49
|
+
oValue[refName.current.value] = refValue.current.value;
|
|
50
|
+
// Reset the name and value
|
|
51
|
+
refName.current.reset();
|
|
52
|
+
refValue.current.value = '';
|
|
53
|
+
}
|
|
54
|
+
// Let the parent know
|
|
55
|
+
props.onChange(oValue);
|
|
56
|
+
}
|
|
57
|
+
// Called when an existing variables needs to be removed
|
|
58
|
+
function remove(name) {
|
|
59
|
+
// Clone the current value
|
|
60
|
+
const oValue = clone(props.value);
|
|
61
|
+
// Delete the given key if it exists
|
|
62
|
+
if (name in oValue) {
|
|
63
|
+
delete oValue[name];
|
|
64
|
+
}
|
|
65
|
+
// Let the parent know
|
|
66
|
+
props.onChange(oValue);
|
|
67
|
+
}
|
|
68
|
+
// Render
|
|
69
|
+
return (React.createElement(Box, null,
|
|
70
|
+
React.createElement(Grid, { container: true, spacing: 1 },
|
|
71
|
+
omap(props.value, (v, k) => React.createElement(React.Fragment, null,
|
|
72
|
+
React.createElement(Grid, { item: true, xs: 5 }, k),
|
|
73
|
+
React.createElement(Grid, { item: true, xs: 5 }, v),
|
|
74
|
+
React.createElement(Grid, { item: true, xs: 2 },
|
|
75
|
+
React.createElement(Tooltip, { title: "More" },
|
|
76
|
+
React.createElement(IconButton, { className: "icon", onClick: ev => remove(k) },
|
|
77
|
+
React.createElement("i", { className: "fa-solid fa-trash-alt" })))))),
|
|
78
|
+
React.createElement(Grid, { item: true, xs: 5, className: "field" },
|
|
79
|
+
React.createElement(DefineNode, { label: "placeholder", name: "name", node: oNameNode, placeholder: "Name", ref: refName, type: "create", variant: "outlined" })),
|
|
80
|
+
React.createElement(Grid, { item: true, xs: 5, className: "field" },
|
|
81
|
+
React.createElement(TextField, { inputRef: refValue, placeholder: "testing value" })),
|
|
82
|
+
React.createElement(Grid, { item: true, xs: 2 },
|
|
83
|
+
React.createElement(Tooltip, { title: "More" },
|
|
84
|
+
React.createElement(IconButton, { className: "icon", onClick: add },
|
|
85
|
+
React.createElement("i", { className: "fa-solid fa-plus" })))))));
|
|
86
|
+
}
|
|
87
|
+
// Valid props
|
|
88
|
+
Variables.propTypes = {
|
|
89
|
+
onChange: PropTypes.func.isRequired,
|
|
90
|
+
value: PropTypes.objectOf(PropTypes.string).isRequired
|
|
91
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Communications Templates Variables
|
|
3
|
+
*
|
|
4
|
+
* Variables component
|
|
5
|
+
*
|
|
6
|
+
* @author Chris Nasr <chris@ouroboroscoding.com>
|
|
7
|
+
* @created 2023-01-20
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Ouroboros modules
|
|
11
|
+
import clone from '@ouroboros/clone';
|
|
12
|
+
import { Node } from '@ouroboros/define';
|
|
13
|
+
import { DefineNode } from '@ouroboros/define-mui';
|
|
14
|
+
import { omap } from '@ouroboros/tools';
|
|
15
|
+
|
|
16
|
+
// NPM modules
|
|
17
|
+
import PropTypes from 'prop-types';
|
|
18
|
+
import React, { useRef } from 'react';
|
|
19
|
+
|
|
20
|
+
// Material UI
|
|
21
|
+
import Box from '@mui/material/Box';
|
|
22
|
+
import Grid from '@mui/material/Grid';
|
|
23
|
+
import IconButton from '@mui/material/IconButton';
|
|
24
|
+
import TextField from '@mui/material/TextField';
|
|
25
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
26
|
+
|
|
27
|
+
// Create hash node
|
|
28
|
+
const oNameNode = new Node({
|
|
29
|
+
__type__: 'string',
|
|
30
|
+
__regex__: '^[a-z_]+$'
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Types
|
|
34
|
+
export type VariablesProps = {
|
|
35
|
+
onChange: (variables: Record<string, string>) => void,
|
|
36
|
+
value: Record<string, string>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Variables
|
|
41
|
+
*
|
|
42
|
+
* Handles template locale management
|
|
43
|
+
*
|
|
44
|
+
* @name Variables
|
|
45
|
+
* @access public
|
|
46
|
+
* @param Object props Properties passed to the component
|
|
47
|
+
* @returns React.Component
|
|
48
|
+
*/
|
|
49
|
+
export default function Variables(props: VariablesProps) {
|
|
50
|
+
|
|
51
|
+
// Refs
|
|
52
|
+
const refName = useRef<DefineNode>(null);
|
|
53
|
+
const refValue = useRef<HTMLInputElement>(null);
|
|
54
|
+
|
|
55
|
+
// Called when a new variable is added
|
|
56
|
+
function add() {
|
|
57
|
+
|
|
58
|
+
// Clone the current value
|
|
59
|
+
const oValue: Record<string, string> = clone(props.value);
|
|
60
|
+
|
|
61
|
+
// If we have references to the inputs
|
|
62
|
+
if(refName.current && refValue.current) {
|
|
63
|
+
|
|
64
|
+
// Add the new item to it
|
|
65
|
+
oValue[refName.current.value] = refValue.current.value;
|
|
66
|
+
|
|
67
|
+
// Reset the name and value
|
|
68
|
+
refName.current.reset();
|
|
69
|
+
refValue.current.value = '';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Let the parent know
|
|
73
|
+
props.onChange(oValue);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Called when an existing variables needs to be removed
|
|
77
|
+
function remove(name: string) {
|
|
78
|
+
|
|
79
|
+
// Clone the current value
|
|
80
|
+
const oValue = clone(props.value);
|
|
81
|
+
|
|
82
|
+
// Delete the given key if it exists
|
|
83
|
+
if(name in oValue) {
|
|
84
|
+
delete oValue[name];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Let the parent know
|
|
88
|
+
props.onChange(oValue);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Render
|
|
92
|
+
return (
|
|
93
|
+
<Box>
|
|
94
|
+
<Grid container spacing={1}>
|
|
95
|
+
{omap(props.value, (v,k) =>
|
|
96
|
+
<React.Fragment>
|
|
97
|
+
<Grid item xs={5}>{k}</Grid>
|
|
98
|
+
<Grid item xs={5}>{v}</Grid>
|
|
99
|
+
<Grid item xs={2}>
|
|
100
|
+
<Tooltip title="More">
|
|
101
|
+
<IconButton className="icon" onClick={ev => remove(k)}>
|
|
102
|
+
<i className="fa-solid fa-trash-alt" />
|
|
103
|
+
</IconButton>
|
|
104
|
+
</Tooltip>
|
|
105
|
+
</Grid>
|
|
106
|
+
</React.Fragment>
|
|
107
|
+
)}
|
|
108
|
+
<Grid item xs={5} className="field">
|
|
109
|
+
<DefineNode
|
|
110
|
+
label="placeholder"
|
|
111
|
+
name="name"
|
|
112
|
+
node={oNameNode}
|
|
113
|
+
placeholder="Name"
|
|
114
|
+
ref={refName}
|
|
115
|
+
type="create"
|
|
116
|
+
variant="outlined"
|
|
117
|
+
/>
|
|
118
|
+
</Grid>
|
|
119
|
+
<Grid item xs={5} className="field">
|
|
120
|
+
<TextField inputRef={refValue} placeholder="testing value" />
|
|
121
|
+
</Grid>
|
|
122
|
+
<Grid item xs={2}>
|
|
123
|
+
<Tooltip title="More">
|
|
124
|
+
<IconButton className="icon" onClick={add}>
|
|
125
|
+
<i className="fa-solid fa-plus" />
|
|
126
|
+
</IconButton>
|
|
127
|
+
</Tooltip>
|
|
128
|
+
</Grid>
|
|
129
|
+
</Grid>
|
|
130
|
+
</Box>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Valid props
|
|
135
|
+
Variables.propTypes = {
|
|
136
|
+
onChange: PropTypes.func.isRequired,
|
|
137
|
+
value: PropTypes.objectOf(PropTypes.string).isRequired
|
|
138
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Communications Templates Template
|
|
3
|
+
*
|
|
4
|
+
* Template 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 { rightsStruct } from '@ouroboros/brain-mui';
|
|
13
|
+
export type contentStruct = {
|
|
14
|
+
_id?: string;
|
|
15
|
+
_created?: number;
|
|
16
|
+
_updated?: number;
|
|
17
|
+
template: string;
|
|
18
|
+
locale: string;
|
|
19
|
+
content?: string;
|
|
20
|
+
subject?: string;
|
|
21
|
+
text?: string;
|
|
22
|
+
type: typeOption;
|
|
23
|
+
html?: string;
|
|
24
|
+
};
|
|
25
|
+
export type templateStruct = {
|
|
26
|
+
_id?: string;
|
|
27
|
+
_created?: number;
|
|
28
|
+
_updated?: number;
|
|
29
|
+
name: string;
|
|
30
|
+
variables: Record<string, string>;
|
|
31
|
+
};
|
|
32
|
+
export type typeOption = 'email' | 'sms';
|
|
33
|
+
export type TemplateProps = {
|
|
34
|
+
locales: Record<string, string>;
|
|
35
|
+
mobile: boolean;
|
|
36
|
+
onChange: (template: templateStruct) => void;
|
|
37
|
+
onError: (error: responseErrorStruct) => void;
|
|
38
|
+
onContent: (type: string) => void;
|
|
39
|
+
rights: {
|
|
40
|
+
template: rightsStruct;
|
|
41
|
+
content: rightsStruct;
|
|
42
|
+
};
|
|
43
|
+
value: templateStruct;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Template
|
|
47
|
+
*
|
|
48
|
+
* Handles a single template
|
|
49
|
+
*
|
|
50
|
+
* @name Template
|
|
51
|
+
* @access public
|
|
52
|
+
* @param Object props Properties passed to the component
|
|
53
|
+
* @returns React.Component
|
|
54
|
+
*/
|
|
55
|
+
declare function Template(props: TemplateProps): JSX.Element;
|
|
56
|
+
declare namespace Template {
|
|
57
|
+
var propTypes: {
|
|
58
|
+
locales: PropTypes.Validator<{
|
|
59
|
+
[x: string]: string | null | undefined;
|
|
60
|
+
}>;
|
|
61
|
+
mobile: PropTypes.Validator<boolean>;
|
|
62
|
+
onChange: PropTypes.Validator<(...args: any[]) => any>;
|
|
63
|
+
onError: PropTypes.Validator<(...args: any[]) => any>;
|
|
64
|
+
onContent: PropTypes.Validator<(...args: any[]) => any>;
|
|
65
|
+
rights: PropTypes.Requireable<Required<PropTypes.InferProps<{
|
|
66
|
+
template: PropTypes.Validator<Required<PropTypes.InferProps<{
|
|
67
|
+
create: PropTypes.Requireable<boolean>;
|
|
68
|
+
delete: PropTypes.Requireable<boolean>;
|
|
69
|
+
read: PropTypes.Requireable<boolean>;
|
|
70
|
+
update: PropTypes.Requireable<boolean>;
|
|
71
|
+
}>>>;
|
|
72
|
+
content: PropTypes.Validator<Required<PropTypes.InferProps<{
|
|
73
|
+
create: PropTypes.Requireable<boolean>;
|
|
74
|
+
delete: PropTypes.Requireable<boolean>;
|
|
75
|
+
read: PropTypes.Requireable<boolean>;
|
|
76
|
+
update: PropTypes.Requireable<boolean>;
|
|
77
|
+
}>>>;
|
|
78
|
+
}>>>;
|
|
79
|
+
value: PropTypes.Validator<Required<PropTypes.InferProps<{
|
|
80
|
+
_id: PropTypes.Validator<string>;
|
|
81
|
+
_created: PropTypes.Requireable<number>;
|
|
82
|
+
_updated: PropTypes.Requireable<number>;
|
|
83
|
+
name: PropTypes.Validator<string>;
|
|
84
|
+
variables: PropTypes.Validator<{
|
|
85
|
+
[x: string]: string | null | undefined;
|
|
86
|
+
}>;
|
|
87
|
+
}>>>;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export default Template;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Communications Templates Template
|
|
3
|
+
*
|
|
4
|
+
* Template 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
|
+
import { afindi, omap, ucfirst } from '@ouroboros/tools';
|
|
16
|
+
// NPM modules
|
|
17
|
+
import PropTypes from 'prop-types';
|
|
18
|
+
import React, { useRef, useState } from 'react';
|
|
19
|
+
// Material UI
|
|
20
|
+
import Box from '@mui/material/Box';
|
|
21
|
+
import Button from '@mui/material/Button';
|
|
22
|
+
import Grid from '@mui/material/Grid';
|
|
23
|
+
import IconButton from '@mui/material/IconButton';
|
|
24
|
+
import Paper from '@mui/material/Paper';
|
|
25
|
+
import Tab from '@mui/material/Tab';
|
|
26
|
+
import Tabs from '@mui/material/Tabs';
|
|
27
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
28
|
+
import Typography from '@mui/material/Typography';
|
|
29
|
+
// Local components
|
|
30
|
+
import ContentCreate from './Content/Create';
|
|
31
|
+
import ContentUpdate from './Content/Update';
|
|
32
|
+
import ContentView from './Content/View';
|
|
33
|
+
import Variables from './Variables';
|
|
34
|
+
// Format Node
|
|
35
|
+
const oNameNode = new Node(TemplateDef.name);
|
|
36
|
+
/**
|
|
37
|
+
* Template
|
|
38
|
+
*
|
|
39
|
+
* Handles a single template
|
|
40
|
+
*
|
|
41
|
+
* @name Template
|
|
42
|
+
* @access public
|
|
43
|
+
* @param Object props Properties passed to the component
|
|
44
|
+
* @returns React.Component
|
|
45
|
+
*/
|
|
46
|
+
export default function Template(props) {
|
|
47
|
+
// State
|
|
48
|
+
const [contents, contentsSet] = useState(false);
|
|
49
|
+
const [tab, tabSet] = useState(0);
|
|
50
|
+
const [edit, editSet] = useState(false);
|
|
51
|
+
const [view, viewSet] = useState(false);
|
|
52
|
+
// Refs
|
|
53
|
+
const refName = useRef(null);
|
|
54
|
+
// Called when the update record changes
|
|
55
|
+
function change(field, value) {
|
|
56
|
+
// Set the new record
|
|
57
|
+
editSet(o => {
|
|
58
|
+
const oRecord = clone(o);
|
|
59
|
+
oRecord[field] = value;
|
|
60
|
+
return oRecord;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Called when a single conent record is created
|
|
64
|
+
function contentCreated(content) {
|
|
65
|
+
// Notify the parent
|
|
66
|
+
props.onContent('create');
|
|
67
|
+
// Clone the current contents
|
|
68
|
+
const lContents = clone(contents);
|
|
69
|
+
// Add the new record to the end of the array
|
|
70
|
+
lContents.push(content);
|
|
71
|
+
// Set the new contents
|
|
72
|
+
contentsSet(lContents);
|
|
73
|
+
}
|
|
74
|
+
// Called when a single content record is updated
|
|
75
|
+
function contentUpdated(content) {
|
|
76
|
+
// Notify the parent
|
|
77
|
+
props.onContent('update');
|
|
78
|
+
// Find the index of the record
|
|
79
|
+
const i = afindi(contents, '_id', content._id);
|
|
80
|
+
// If we got an index
|
|
81
|
+
if (i > -1) {
|
|
82
|
+
// Clone the current contents, merge the current record with the
|
|
83
|
+
// new one, and set the new contents
|
|
84
|
+
const lContents = clone(contents);
|
|
85
|
+
lContents[i] = { ...lContents[i], ...content };
|
|
86
|
+
contentsSet(lContents);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Called to delete the template
|
|
90
|
+
function remove() {
|
|
91
|
+
throw new Error('Remove template not implemented');
|
|
92
|
+
}
|
|
93
|
+
// Called to update the template
|
|
94
|
+
function update() {
|
|
95
|
+
// Create the data in the system
|
|
96
|
+
mouth.update('template', edit).then((data) => {
|
|
97
|
+
// Hide the form
|
|
98
|
+
editSet(false);
|
|
99
|
+
// Let the parent know
|
|
100
|
+
props.onChange(edit);
|
|
101
|
+
}, (error) => {
|
|
102
|
+
if (error.code === errors.body.DB_DUPLICATE) {
|
|
103
|
+
refName.current?.error('Duplicate');
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// View toggle
|
|
111
|
+
function viewToggle() {
|
|
112
|
+
if (view) {
|
|
113
|
+
viewSet(false);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
if (contents === false) {
|
|
117
|
+
mouth.read('template/contents', {
|
|
118
|
+
template: props.value._id
|
|
119
|
+
}).then(contentsSet);
|
|
120
|
+
}
|
|
121
|
+
viewSet(true);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Render
|
|
125
|
+
return (React.createElement(Paper, { className: "template padding" },
|
|
126
|
+
React.createElement(Box, { className: "flexColumns" },
|
|
127
|
+
React.createElement(Box, { className: "flexGrow link", onClick: viewToggle },
|
|
128
|
+
React.createElement("h2", null,
|
|
129
|
+
ucfirst(props.value.name.replace(/_/g, ' ')),
|
|
130
|
+
"\u00A0\u00A0",
|
|
131
|
+
React.createElement("i", { className: 'fa-solid fa-angle-' + (view ? 'up' : 'down') }))),
|
|
132
|
+
React.createElement(Box, { className: "flexStatic" },
|
|
133
|
+
props.rights.template.update &&
|
|
134
|
+
React.createElement(Tooltip, { title: "Edit the Template" },
|
|
135
|
+
React.createElement(IconButton, { className: "icon", onClick: ev => editSet(edit ? false : clone(props.value)) },
|
|
136
|
+
React.createElement("i", { className: 'fa-solid fa-edit ' + (edit ? 'open' : 'closed') }))),
|
|
137
|
+
props.rights.template.delete &&
|
|
138
|
+
React.createElement(Tooltip, { title: "Delete the Template" },
|
|
139
|
+
React.createElement(IconButton, { className: "icon", onClick: remove },
|
|
140
|
+
React.createElement("i", { className: "fa-solid fa-trash-alt" }))))),
|
|
141
|
+
edit &&
|
|
142
|
+
React.createElement(React.Fragment, null,
|
|
143
|
+
React.createElement("hr", null),
|
|
144
|
+
React.createElement("h3", null, "Update Template"),
|
|
145
|
+
React.createElement(Grid, { container: true, spacing: 2 },
|
|
146
|
+
React.createElement(Grid, { item: true, lg: 6, md: 12, className: "field" },
|
|
147
|
+
React.createElement(Typography, null,
|
|
148
|
+
React.createElement("strong", null, "Name")),
|
|
149
|
+
React.createElement(DefineNode, { label: "none", name: "name", node: oNameNode, onChange: value => change('name', value), onEnterPressed: update, ref: refName, type: "update", value: edit.name })),
|
|
150
|
+
React.createElement(Grid, { item: true, lg: 6, md: 12 },
|
|
151
|
+
React.createElement(Typography, null,
|
|
152
|
+
React.createElement("strong", null, "Variables")),
|
|
153
|
+
React.createElement(Variables, { onChange: value => change('variables', value), value: edit.variables || {} })),
|
|
154
|
+
React.createElement(Grid, { item: true, xs: 12, className: "actions" },
|
|
155
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => editSet(false) }, "Cancel"),
|
|
156
|
+
React.createElement(Button, { variant: "contained", color: "primary", onClick: update }, "Save")))),
|
|
157
|
+
!edit && view &&
|
|
158
|
+
React.createElement(React.Fragment, null,
|
|
159
|
+
React.createElement("hr", null),
|
|
160
|
+
React.createElement(Grid, { container: true, spacing: 1 },
|
|
161
|
+
React.createElement(Grid, { item: true, xs: 12, md: 9, xl: 10 },
|
|
162
|
+
React.createElement(Tabs, { onChange: (ev, val) => tabSet(val), scrollButtons: "auto", variant: "scrollable", value: tab },
|
|
163
|
+
contents && contents.map(o => React.createElement(Tab, { key: o._id, label: props.locales[o.locale] + ' ' + o.type })),
|
|
164
|
+
props.rights.content.create &&
|
|
165
|
+
React.createElement(Tab, { label: React.createElement("i", { className: "fa-solid fa-plus" }) })),
|
|
166
|
+
React.createElement(Box, { className: "padding" },
|
|
167
|
+
React.createElement("br", null),
|
|
168
|
+
(contents && tab < contents.length &&
|
|
169
|
+
(props.rights.content.update ?
|
|
170
|
+
React.createElement(ContentUpdate, { key: contents[tab]._id, mobile: props.mobile, onError: props.onError, onUpdated: contentUpdated, value: contents[tab] })
|
|
171
|
+
:
|
|
172
|
+
React.createElement(ContentView, { key: contents[tab]._id, mobile: props.mobile, onError: props.onError, value: contents[tab] }))) ||
|
|
173
|
+
((props.rights.content.create && contents && tab === contents.length) &&
|
|
174
|
+
React.createElement(ContentCreate, { locales: props.locales, mobile: props.mobile, onCreated: contentCreated, onError: props.onError, template: props.value._id })))),
|
|
175
|
+
React.createElement(Grid, { item: true, xs: 12, md: 3, xl: 2 },
|
|
176
|
+
React.createElement("h4", null, "Available Variables"),
|
|
177
|
+
props.value && omap(props.value.variables, (v, k) => React.createElement(Typography, { key: k }, '{' + k + '}')))))));
|
|
178
|
+
}
|
|
179
|
+
// Valid props
|
|
180
|
+
Template.propTypes = {
|
|
181
|
+
locales: PropTypes.objectOf(PropTypes.string).isRequired,
|
|
182
|
+
mobile: PropTypes.bool.isRequired,
|
|
183
|
+
onChange: PropTypes.func.isRequired,
|
|
184
|
+
onError: PropTypes.func.isRequired,
|
|
185
|
+
onContent: PropTypes.func.isRequired,
|
|
186
|
+
rights: PropTypes.exact({
|
|
187
|
+
template: PropTypes.exact({
|
|
188
|
+
create: PropTypes.bool,
|
|
189
|
+
delete: PropTypes.bool,
|
|
190
|
+
read: PropTypes.bool,
|
|
191
|
+
update: PropTypes.bool
|
|
192
|
+
}).isRequired,
|
|
193
|
+
content: PropTypes.exact({
|
|
194
|
+
create: PropTypes.bool,
|
|
195
|
+
delete: PropTypes.bool,
|
|
196
|
+
read: PropTypes.bool,
|
|
197
|
+
update: PropTypes.bool
|
|
198
|
+
}).isRequired
|
|
199
|
+
}),
|
|
200
|
+
value: PropTypes.exact({
|
|
201
|
+
_id: PropTypes.string.isRequired,
|
|
202
|
+
_created: PropTypes.number,
|
|
203
|
+
_updated: PropTypes.number,
|
|
204
|
+
name: PropTypes.string.isRequired,
|
|
205
|
+
variables: PropTypes.objectOf(PropTypes.string).isRequired
|
|
206
|
+
}).isRequired
|
|
207
|
+
};
|