Mail Templates + Frontend
This commit is contained in:
parent
f5a8f2c777
commit
33dd990b71
@ -98,6 +98,18 @@ namespace Api {
|
|||||||
|
|
||||||
return ($this->success && !empty($res) ? $res : array());
|
return ($this->success && !empty($res) ? $res : array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getMessageTemplate($key) {
|
||||||
|
$req = new \Api\Settings\Get($this->user);
|
||||||
|
$this->success = $req->execute(array("key" => $key));
|
||||||
|
$this->lastError = $req->getLastError();
|
||||||
|
|
||||||
|
if ($this->success) {
|
||||||
|
return $req->getResult()["settings"][$key] ?? "{{link}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -386,19 +398,39 @@ namespace Api\User {
|
|||||||
|
|
||||||
//send validation mail
|
//send validation mail
|
||||||
if ($this->success) {
|
if ($this->success) {
|
||||||
$request = new SendMail($this->user);
|
|
||||||
$link = "http://localhost/acceptInvitation?token=$token";
|
$settings = $this->user->getConfiguration()->getSettings();
|
||||||
$this->success = $request->execute(array(
|
$baseUrl = htmlspecialchars($settings->getBaseUrl());
|
||||||
"from" => "webmaster@romanh.de",
|
$siteName = htmlspecialchars($settings->getSiteName());
|
||||||
|
$body = $this->getMessageTemplate("message_accept_invite");
|
||||||
|
|
||||||
|
if ($this->success) {
|
||||||
|
|
||||||
|
$replacements = array(
|
||||||
|
"link" => "$baseUrl/acceptInvite?token=$token",
|
||||||
|
"site_name" => $siteName,
|
||||||
|
"base_url" => $baseUrl,
|
||||||
|
"username" => htmlspecialchars($username)
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($replacements as $key => $value) {
|
||||||
|
$body = str_replace("{{{$key}}}", $value, $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = new SendMail($this->user);
|
||||||
|
$this->success = $request->execute(array(
|
||||||
"to" => $email,
|
"to" => $email,
|
||||||
"subject" => "Account Invitation for web-base@localhost",
|
"subject" => "[$siteName] Account Invitation",
|
||||||
"body" =>
|
"body" => $body
|
||||||
"Hello,<br>
|
));
|
||||||
you were invited to create an account on web-base@localhost. Click on the following link to confirm the registration, it is 48h valid from now.
|
|
||||||
If the invitation was not intended, you can simply ignore this email.<br><br><a href=\"$link\">$link</a>"
|
$this->lastError = $request->getLastError();
|
||||||
)
|
}
|
||||||
);
|
|
||||||
$this->lastError = $request->getLastError();
|
if (!$this->success) {
|
||||||
|
$this->lastError = "The invitation was created but the confirmation email could not be sent. " .
|
||||||
|
"Please contact the server administration. Reason: " . $this->lastError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $this->success;
|
return $this->success;
|
||||||
}
|
}
|
||||||
@ -573,22 +605,36 @@ If the invitation was not intended, you can simply ignore this email.<br><br><a
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = new SendMail($this->user);
|
$settings = $this->user->getConfiguration()->getSettings();
|
||||||
$link = "http://localhost/confirmEmail?token=$this->token";
|
$baseUrl = htmlspecialchars($settings->getBaseUrl());
|
||||||
$this->success = $request->execute(array(
|
$siteName = htmlspecialchars($settings->getSiteName());
|
||||||
"from" => "webmaster@romanh.de",
|
$body = $this->getMessageTemplate("message_confirm_email");
|
||||||
"to" => $email,
|
|
||||||
"subject" => "E-Mail Confirmation for web-base@localhost",
|
if ($this->success) {
|
||||||
"body" =>
|
|
||||||
"Hello,<br>
|
$replacements = array(
|
||||||
you recently registered an account on web-base@localhost. Click on the following link to confirm the registration, it is 48h valid from now.
|
"link" => "$baseUrl/confirmEmail?token=$this->token",
|
||||||
If the registration was not intended, you can simply ignore this email.<br><br><a href=\"$link\">$link</a>"
|
"site_name" => $siteName,
|
||||||
)
|
"base_url" => $baseUrl,
|
||||||
);
|
"username" => htmlspecialchars($username)
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($replacements as $key => $value) {
|
||||||
|
$body = str_replace("{{{$key}}}", $value, $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = new SendMail($this->user);
|
||||||
|
$this->success = $request->execute(array(
|
||||||
|
"to" => $email,
|
||||||
|
"subject" => "[$siteName] E-Mail Confirmation",
|
||||||
|
"body" => $body
|
||||||
|
));
|
||||||
|
$this->lastError = $request->getLastError();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->success) {
|
if (!$this->success) {
|
||||||
$this->lastError = "Your account was registered but the confirmation email could not be sent. " .
|
$this->lastError = "Your account was registered but the confirmation email could not be sent. " .
|
||||||
"Please contact the server administration. Reason: " . $request->getLastError();
|
"Please contact the server administration. Reason: " . $this->lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->success;
|
return $this->success;
|
||||||
|
@ -165,37 +165,31 @@ class CreateDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static function MessageConfirmEmail() : string {
|
private static function MessageConfirmEmail() : string {
|
||||||
return str_replace("\n", "", intendCode(
|
return "Hello {{username}},<br>" .
|
||||||
"Hello {{username}},<br>
|
"You recently created an account on {{site_name}}. Please click on the following link to " .
|
||||||
You recently created an account on {{site_name}}. Please click on the following link to
|
"confirm your email address and complete your registration. If you haven't registered an " .
|
||||||
confirm your email address and complete your registration. If you haven't registered an
|
"account, you can simply ignore this email. The link is valid for the next 48 hours:<br><br> " .
|
||||||
account, you can simply ignore this email. The link is valid for the next 48 hours:<br><br>
|
"<a href=\"{{link}}\">{{link}}</a><br><br> " .
|
||||||
<a href=\"{{link}}\">{{confirm_link}}</a><br><br>
|
"Best Regards<br> " .
|
||||||
Best Regards<br>
|
"{{site_name}} Administration";
|
||||||
{{site_name}} Administration", false
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function MessageAcceptInvite() : string {
|
private static function MessageAcceptInvite() : string {
|
||||||
return str_replace("\n", "", intendCode(
|
return "Hello {{username}},<br>" .
|
||||||
"Hello {{username}},<br>
|
"You were invited to create an account on {{site_name}}. Please click on the following link to " .
|
||||||
You were invited to create an account on {{site_name}}. Please click on the following link to
|
"confirm your email address and complete your registration by choosing a new password. " .
|
||||||
confirm your email address and complete your registration by choosing a new password.
|
"If you want to decline the invitation, you can simply ignore this email. The link is valid for the next 48 hours:<br><br>" .
|
||||||
If you want to decline the invitation, you can simply ignore this email. The link is valid for the next 48 hours:<br><br>
|
"<a href=\"{{link}}\">{{link}}</a><br><br>" .
|
||||||
<a href=\"{{link}}\">{{link}}</a><br><br>
|
"Best Regards<br>" .
|
||||||
Best Regards<br>
|
"{{site_name}} Administration";
|
||||||
{{site_name}} Administration", false
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function MessageResetPassword() : string {
|
private static function MessageResetPassword() : string {
|
||||||
return str_replace("\n", "", intendCode(
|
return "Hello {{username}},<br>" .
|
||||||
"Hello {{username}},<br>
|
"you requested a password reset on {{sitename}}. Please click on the following link to " .
|
||||||
you requested a password reset on {{sitename}}. Please click on the following link to
|
"choose a new password. If this request was not intended, you can simply ignore the email. The Link is valid for one hour:<br><br>" .
|
||||||
choose a new password. If this request was not intended, you can simply ignore the email. The Link is valid for one hour:<br><br>
|
"<a href=\"{{link}}\">{{link}}</a><br><br>" .
|
||||||
<a href=\"{{link}}\">{{link}}</a><br><br>
|
"Best Regards<br>" .
|
||||||
Best Regards<br>
|
"{{site_name}} Administration";
|
||||||
{{site_name}} Administration", false
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,4 +68,12 @@ class Settings {
|
|||||||
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true)
|
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true)
|
||||||
->addRow("jwt_secret", $this->jwtSecret, true);
|
->addRow("jwt_secret", $this->jwtSecret, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSiteName() {
|
||||||
|
return $this->siteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBaseUrl() {
|
||||||
|
return $this->baseUrl;
|
||||||
|
}
|
||||||
}
|
}
|
14
js/admin.min.js
vendored
14
js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
54
src/package-lock.json
generated
54
src/package-lock.json
generated
@ -11830,6 +11830,55 @@
|
|||||||
"walker": "~1.0.5"
|
"walker": "~1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sanitize-html": {
|
||||||
|
"version": "1.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.0.tgz",
|
||||||
|
"integrity": "sha512-U1btucGeYVpg0GoK43jPpe/bDCV4cBOGuxzv5NBd0bOjyZdMKY0n98S/vNlO1wVwre0VCj8H3hbzE7gD2+RjKA==",
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"htmlparser2": "^4.1.0",
|
||||||
|
"lodash": "^4.17.15",
|
||||||
|
"postcss": "^7.0.27",
|
||||||
|
"srcset": "^2.0.1",
|
||||||
|
"xtend": "^4.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
|
||||||
|
},
|
||||||
|
"domhandler": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domutils": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-serializer": "^0.2.1",
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"htmlparser2": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^3.0.0",
|
||||||
|
"domutils": "^2.0.0",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sanitize.css": {
|
"sanitize.css": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz",
|
||||||
@ -12450,6 +12499,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||||
},
|
},
|
||||||
|
"srcset": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/srcset/-/srcset-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-00kZI87TdRKwt+P8jj8UZxbfp7mK2ufxcIMWvhAOZNJTRROimpHeruWrGvCZneiuVDLqdyHefVp748ECTnyUBQ=="
|
||||||
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^3.4.1",
|
"react-scripts": "^3.4.1",
|
||||||
"react-select": "^3.1.0",
|
"react-select": "^3.1.0",
|
||||||
"react-tooltip": "^4.2.7"
|
"react-tooltip": "^4.2.7",
|
||||||
|
"sanitize-html": "^1.27.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --mode development && mv dist/main.js ../js/admin.min.js"
|
"build": "webpack --mode development && mv dist/main.js ../js/admin.min.js"
|
||||||
|
@ -3,11 +3,13 @@ import {Link} from "react-router-dom";
|
|||||||
import Alert from "../elements/alert";
|
import Alert from "../elements/alert";
|
||||||
import {Collapse} from "react-collapse/lib/Collapse";
|
import {Collapse} from "react-collapse/lib/Collapse";
|
||||||
import Icon from "../elements/icon";
|
import Icon from "../elements/icon";
|
||||||
import { EditorState, ContentState, convertFromHTML, convertToRaw } from 'draft-js'
|
import { EditorState, ContentState, convertToRaw } from 'draft-js'
|
||||||
import { Editor } from 'react-draft-wysiwyg'
|
import { Editor } from 'react-draft-wysiwyg'
|
||||||
import draftToHtml from 'draftjs-to-html';
|
import draftToHtml from 'draftjs-to-html';
|
||||||
import htmlToDraft from 'html-to-draftjs';
|
import htmlToDraft from 'html-to-draftjs';
|
||||||
|
import sanitizeHtml from 'sanitize-html'
|
||||||
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
|
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
|
||||||
|
import ReactTooltip from "react-tooltip";
|
||||||
|
|
||||||
export default class Settings extends React.Component {
|
export default class Settings extends React.Component {
|
||||||
|
|
||||||
@ -302,11 +304,16 @@ export default class Settings extends React.Component {
|
|||||||
<div className={"form-group"} key={"group-" + key}>
|
<div className={"form-group"} key={"group-" + key}>
|
||||||
<label htmlFor={key}>
|
<label htmlFor={key}>
|
||||||
{ title }
|
{ title }
|
||||||
|
<ReactTooltip id={"tooltip-" + key} />
|
||||||
<Icon icon={"times"} className={"ml-2 text-danger"} style={{cursor: "pointer"}}
|
<Icon icon={"times"} className={"ml-2 text-danger"} style={{cursor: "pointer"}}
|
||||||
onClick={() => this.closeEditor(false)}
|
onClick={() => this.closeEditor(false)} data-type={"error"}
|
||||||
|
data-tip={"Discard Changes"} data-place={"top"} data-effect={"solid"}
|
||||||
|
data-for={"tooltip-" + key}
|
||||||
/>
|
/>
|
||||||
<Icon icon={"check"} className={"ml-1 text-success"} style={{cursor: "pointer"}}
|
<Icon icon={"check"} className={"ml-2 text-success"} style={{cursor: "pointer"}}
|
||||||
onClick={() => this.closeEditor(true)}
|
onClick={() => this.closeEditor(true)} data-type={"success"}
|
||||||
|
data-tip={"Save Changes"} data-place={"top"} data-effect={"solid"}
|
||||||
|
data-for={"tooltip-" + key}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
{ editor }
|
{ editor }
|
||||||
@ -315,15 +322,16 @@ export default class Settings extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
formGroups.push(
|
formGroups.push(
|
||||||
<div className={"form-group"} key={"group-" + key}>
|
<div className={"form-group"} key={"group-" + key}>
|
||||||
|
<ReactTooltip id={"tooltip-" + key} />
|
||||||
<label htmlFor={key}>
|
<label htmlFor={key}>
|
||||||
{ title }
|
{ title }
|
||||||
<Icon icon={"pencil-alt"} className={"ml-2"} style={{cursor: "pointer"}}
|
<Icon icon={"pencil-alt"} className={"ml-2"} style={{cursor: "pointer"}}
|
||||||
onClick={() => this.openEditor(key)}
|
onClick={() => this.openEditor(key)} data-type={"info"}
|
||||||
|
data-tip={"Edit Template"} data-place={"top"} data-effect={"solid"}
|
||||||
|
data-for={"tooltip-" + key}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<textarea rows={6} className={"form-control"} disabled={true}
|
<div className={"p-2 text-black"} style={{backgroundColor: "#d2d6de"}} dangerouslySetInnerHTML={{ __html: sanitizeHtml(this.state.settings[key] ?? "") }} />
|
||||||
value={this.state.settings[key] ?? ""} id={key} name={key}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -332,77 +340,10 @@ export default class Settings extends React.Component {
|
|||||||
return formGroups;
|
return formGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
getUncategorizedForm() {
|
||||||
|
return <b>Coming soon…</b>
|
||||||
getUncategorisedCard() {
|
|
||||||
|
|
||||||
let keys = [];
|
|
||||||
let tr = [];
|
|
||||||
for (let key in this.state.settings) {
|
|
||||||
if (this.state.settings.hasOwnProperty(key)) {
|
|
||||||
if (!this.generalKeys.includes(key) && !this.mailKeys.includes(key)) {
|
|
||||||
keys.push(key);
|
|
||||||
tr.push(<tr key={"tr-" + key}>
|
|
||||||
<td>{key}</td>
|
|
||||||
<td>{this.state.settings[key]}</td>
|
|
||||||
</tr>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let errors = [];
|
|
||||||
for (let i = 0; i < this.state.etcErrors.length; i++) {
|
|
||||||
errors.push(<Alert key={"error-" + i} onClose={() => this.removeError("etcErrors", i)} {...this.state.etcErrors[i]}/>)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<div className={"card-header"} style={{cursor: "pointer"}}
|
|
||||||
onClick={() => this.toggleCollapse("etcOpened")}>
|
|
||||||
<h4 className={"card-title"}>
|
|
||||||
<Icon className={"mr-2"} icon={"cogs"}/>
|
|
||||||
General Settings
|
|
||||||
</h4>
|
|
||||||
<div className={"card-tools"}>
|
|
||||||
<span className={"btn btn-tool btn-sm"}>
|
|
||||||
<Icon icon={this.state.etcOpened ? "angle-up" : "angle-down"}/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Collapse isOpened={this.state.etcOpened}>
|
|
||||||
<div className={"card-body"}>
|
|
||||||
<div className={"row"}>
|
|
||||||
<div className={"col-12 col-lg-6"}>
|
|
||||||
{errors}
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Key</th>
|
|
||||||
<th>Value</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{tr}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div>
|
|
||||||
<button className={"btn btn-secondary ml-2"} onClick={() => this.onReset("etcErrors", keys)}
|
|
||||||
disabled={this.state.isResetting || this.state.isSaving}>
|
|
||||||
{this.state.isResetting ?
|
|
||||||
<span>Resetting <Icon icon={"circle-notch"}/></span> : "Reset"}
|
|
||||||
</button>
|
|
||||||
<button className={"btn btn-success ml-2"} onClick={() => this.onSave("etcErrors", keys)}
|
|
||||||
disabled={this.state.isResetting || this.state.isSaving}>
|
|
||||||
{this.state.isSaving ?
|
|
||||||
<span>Saving <Icon icon={"circle-notch"}/></span> : "Save"}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Collapse>
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
let errors = [];
|
let errors = [];
|
||||||
@ -415,7 +356,7 @@ export default class Settings extends React.Component {
|
|||||||
"general": {color: "primary", icon: "cogs", title: "General Settings", content: this.createGeneralForm()},
|
"general": {color: "primary", icon: "cogs", title: "General Settings", content: this.createGeneralForm()},
|
||||||
"mail": {color: "warning", icon: "envelope", title: "Mail Settings", content: this.createMailForm()},
|
"mail": {color: "warning", icon: "envelope", title: "Mail Settings", content: this.createMailForm()},
|
||||||
"messages": {color: "info", icon: "copy", title: "Message Templates", content: this.getMessagesForm()},
|
"messages": {color: "info", icon: "copy", title: "Message Templates", content: this.getMessagesForm()},
|
||||||
"uncategorised": {color: "secondary", icon: "stream", title: "Uncategorised", content: <></>},
|
"uncategorised": {color: "secondary", icon: "stream", title: "Uncategorised", content: this.getUncategorizedForm()},
|
||||||
};
|
};
|
||||||
|
|
||||||
let cards = [];
|
let cards = [];
|
||||||
@ -446,10 +387,11 @@ export default class Settings extends React.Component {
|
|||||||
{cards}
|
{cards}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ReactTooltip />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditorStateChange(editorState, key) {
|
onEditorStateChange(editorState) {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
messages: {
|
messages: {
|
||||||
|
Loading…
Reference in New Issue
Block a user