Mail Templates + Frontend
This commit is contained in:
1 parent
f5a8f2c777
commit
33dd990b71
7 files changed
+187
-130
No files matched your search
+69
-23
@@ -98,6 +98,18 @@ namespace Api {
|
||||
|
||||
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,20 +398,40 @@ namespace Api\User {
|
||||
|
||||
//send validation mail
|
||||
if ($this->success) {
|
||||
$request = new SendMail($this->user);
|
||||
$link = "http://localhost/acceptInvitation?token=$token";
|
||||
$this->success = $request->execute(array(
|
||||
"from" => "webmaster@romanh.de",
|
||||
"to" => $email,
|
||||
"subject" => "Account Invitation for web-base@localhost",
|
||||
"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>"
|
||||
)
|
||||
|
||||
$settings = $this->user->getConfiguration()->getSettings();
|
||||
$baseUrl = htmlspecialchars($settings->getBaseUrl());
|
||||
$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,
|
||||
"subject" => "[$siteName] Account Invitation",
|
||||
"body" => $body
|
||||
));
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
@@ -573,22 +605,36 @@ If the invitation was not intended, you can simply ignore this email.<br><br><a
|
||||
return false;
|
||||
}
|
||||
|
||||
$request = new SendMail($this->user);
|
||||
$link = "http://localhost/confirmEmail?token=$this->token";
|
||||
$this->success = $request->execute(array(
|
||||
"from" => "webmaster@romanh.de",
|
||||
"to" => $email,
|
||||
"subject" => "E-Mail Confirmation for web-base@localhost",
|
||||
"body" =>
|
||||
"Hello,<br>
|
||||
you recently registered an account on web-base@localhost. Click on the following link to confirm the registration, it is 48h valid from now.
|
||||
If the registration was not intended, you can simply ignore this email.<br><br><a href=\"$link\">$link</a>"
|
||||
)
|
||||
$settings = $this->user->getConfiguration()->getSettings();
|
||||
$baseUrl = htmlspecialchars($settings->getBaseUrl());
|
||||
$siteName = htmlspecialchars($settings->getSiteName());
|
||||
$body = $this->getMessageTemplate("message_confirm_email");
|
||||
|
||||
if ($this->success) {
|
||||
|
||||
$replacements = array(
|
||||
"link" => "$baseUrl/confirmEmail?token=$this->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,
|
||||
"subject" => "[$siteName] E-Mail Confirmation",
|
||||
"body" => $body
|
||||
));
|
||||
$this->lastError = $request->getLastError();
|
||||
}
|
||||
|
||||
if (!$this->success) {
|
||||
$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;
|
||||
|
||||
@@ -165,37 +165,31 @@ class CreateDatabase {
|
||||
}
|
||||
|
||||
private static function MessageConfirmEmail() : string {
|
||||
return str_replace("\n", "", intendCode(
|
||||
"Hello {{username}},<br>
|
||||
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
|
||||
account, you can simply ignore this email. The link is valid for the next 48 hours:<br><br>
|
||||
<a href=\"{{link}}\">{{confirm_link}}</a><br><br>
|
||||
Best Regards<br>
|
||||
{{site_name}} Administration", false
|
||||
));
|
||||
return "Hello {{username}},<br>" .
|
||||
"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 " .
|
||||
"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> " .
|
||||
"Best Regards<br> " .
|
||||
"{{site_name}} Administration";
|
||||
}
|
||||
|
||||
private static function MessageAcceptInvite() : string {
|
||||
return str_replace("\n", "", intendCode(
|
||||
"Hello {{username}},<br>
|
||||
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.
|
||||
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>
|
||||
Best Regards<br>
|
||||
{{site_name}} Administration", false
|
||||
));
|
||||
return "Hello {{username}},<br>" .
|
||||
"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. " .
|
||||
"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>" .
|
||||
"Best Regards<br>" .
|
||||
"{{site_name}} Administration";
|
||||
}
|
||||
|
||||
private static function MessageResetPassword() : string {
|
||||
return str_replace("\n", "", intendCode(
|
||||
"Hello {{username}},<br>
|
||||
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>
|
||||
<a href=\"{{link}}\">{{link}}</a><br><br>
|
||||
Best Regards<br>
|
||||
{{site_name}} Administration", false
|
||||
));
|
||||
return "Hello {{username}},<br>" .
|
||||
"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>" .
|
||||
"<a href=\"{{link}}\">{{link}}</a><br><br>" .
|
||||
"Best Regards<br>" .
|
||||
"{{site_name}} Administration";
|
||||
}
|
||||
}
|
||||
@@ -68,4 +68,12 @@ class Settings {
|
||||
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true)
|
||||
->addRow("jwt_secret", $this->jwtSecret, true);
|
||||
}
|
||||
|
||||
public function getSiteName() {
|
||||
return $this->siteName;
|
||||
}
|
||||
|
||||
public function getBaseUrl() {
|
||||
return $this->baseUrl;
|
||||
}
|
||||
}
|
||||
Vendored
+13
-1
@@ -11033,6 +11033,18 @@ eval("__webpack_require__.r(__webpack_exports__);\nfunction isAbsolute(pathname)
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/sanitize-html/dist/sanitize-html.js":
|
||||
/*!**********************************************************!*\
|
||||
!*** ./node_modules/sanitize-html/dist/sanitize-html.js ***!
|
||||
\**********************************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
eval("/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var require;var require;function _createForOfIteratorHelper(o,allowArrayLike){var it;if(typeof Symbol===\"undefined\"||o[Symbol.iterator]==null){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length===\"number\"){if(it)o=it;var i=0;var F=function F(){};return{s:F,n:function n(){if(i>=o.length)return{done:true};return{done:false,value:o[i++]};},e:function e(_e){throw _e;},f:F};}throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");}var normalCompletion=true,didErr=false,err;return{s:function s(){it=o[Symbol.iterator]();},n:function n(){var step=it.next();normalCompletion=step.done;return step;},e:function e(_e2){didErr=true;err=_e2;},f:function f(){try{if(!normalCompletion&&it[\"return\"]!=null)it[\"return\"]();}finally{if(didErr)throw err;}}};}function _toConsumableArray(arr){return _arrayWithoutHoles(arr)||_iterableToArray(arr)||_unsupportedIterableToArray(arr)||_nonIterableSpread();}function _nonIterableSpread(){throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o===\"string\")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n===\"Object\"&&o.constructor)n=o.constructor.name;if(n===\"Map\"||n===\"Set\")return Array.from(o);if(n===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen);}function _iterableToArray(iter){if(typeof Symbol!==\"undefined\"&&Symbol.iterator in Object(iter))return Array.from(iter);}function _arrayWithoutHoles(arr){if(Array.isArray(arr))return _arrayLikeToArray(arr);}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++){arr2[i]=arr[i];}return arr2;}function _typeof(obj){\"@babel/helpers - typeof\";if(typeof Symbol===\"function\"&&typeof Symbol.iterator===\"symbol\"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol===\"function\"&&obj.constructor===Symbol&&obj!==Symbol.prototype?\"symbol\":typeof obj;};}return _typeof(obj);}(function(f){if(( false?undefined:_typeof(exports))===\"object\"&&typeof module!==\"undefined\"){module.exports=f();}else if(true){!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (f),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));}else{ var g; }})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return require(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++){o(t[i]);}return o;}return r;}()({1:[function(require,module,exports){'use strict';exports.byteLength=byteLength;exports.toByteArray=toByteArray;exports.fromByteArray=fromByteArray;var lookup=[];var revLookup=[];var Arr=typeof Uint8Array!=='undefined'?Uint8Array:Array;var code='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';for(var i=0,len=code.length;i<len;++i){lookup[i]=code[i];revLookup[code.charCodeAt(i)]=i;}// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)]=62;revLookup['_'.charCodeAt(0)]=63;function getLens(b64){var len=b64.length;if(len%4>0){throw new Error('Invalid string. Length must be a multiple of 4');}// Trim off extra bytes after placeholder bytes are found\n// See: https://github.com/beatgammit/base64-js/issues/42\nvar validLen=b64.indexOf('=');if(validLen===-1)validLen=len;var placeHoldersLen=validLen===len?0:4-validLen%4;return[validLen,placeHoldersLen];}// base64 is 4/3 + up to two characters of the original data\nfunction byteLength(b64){var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];return(validLen+placeHoldersLen)*3/4-placeHoldersLen;}function _byteLength(b64,validLen,placeHoldersLen){return(validLen+placeHoldersLen)*3/4-placeHoldersLen;}function toByteArray(b64){var tmp;var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];var arr=new Arr(_byteLength(b64,validLen,placeHoldersLen));
Line truncated
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/scheduler/cjs/scheduler-tracing.development.js":
|
||||
/*!*********************************************************************!*\
|
||||
!*** ./node_modules/scheduler/cjs/scheduler-tracing.development.js ***!
|
||||
@@ -11439,7 +11451,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Settings; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/esm/react-router-dom.js\");\n/* harmony import */ var _elements_alert__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../elements/alert */ \"./src/elements/alert.js\");\n/* harmony import */ var react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-collapse/lib/Collapse */ \"./node_modules/react-collapse/lib/Collapse.js\");\n/* harmony import */ var react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _elements_icon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../elements/icon */ \"./src/elements/icon.js\");\n/* harmony import */ var draft_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! draft-js */ \"./node_modules/draft-js/lib/Draft.js\");\n/* harmony import */ var draft_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(draft_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react-draft-wysiwyg */ \"./node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.js\");\n/* harmony import */ var react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var draftjs_to_html__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! draftjs-to-html */ \"./node_modules/draftjs-to-html/lib/draftjs-to-html.js\");\n/* harmony import */ var draftjs_to_html__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(draftjs_to_html__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var html_to_draftjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! html-to-draftjs */ \"./node_modules/html-to-draftjs/dist/html-to-draftjs.js\");\n/* harmony import */ var html_to_draftjs__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(html_to_draftjs__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! react-draft-wysiwyg/dist/react-draft-wysiwyg.css */ \"./node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css\");\n/* harmony import */ var react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_9__);\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null ||Line truncated
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Settings; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/esm/react-router-dom.js\");\n/* harmony import */ var _elements_alert__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../elements/alert */ \"./src/elements/alert.js\");\n/* harmony import */ var react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-collapse/lib/Collapse */ \"./node_modules/react-collapse/lib/Collapse.js\");\n/* harmony import */ var react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_collapse_lib_Collapse__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _elements_icon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../elements/icon */ \"./src/elements/icon.js\");\n/* harmony import */ var draft_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! draft-js */ \"./node_modules/draft-js/lib/Draft.js\");\n/* harmony import */ var draft_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(draft_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react-draft-wysiwyg */ \"./node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.js\");\n/* harmony import */ var react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(react_draft_wysiwyg__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var draftjs_to_html__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! draftjs-to-html */ \"./node_modules/draftjs-to-html/lib/draftjs-to-html.js\");\n/* harmony import */ var draftjs_to_html__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(draftjs_to_html__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var html_to_draftjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! html-to-draftjs */ \"./node_modules/html-to-draftjs/dist/html-to-draftjs.js\");\n/* harmony import */ var html_to_draftjs__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(html_to_draftjs__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var sanitize_html__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! sanitize-html */ \"./node_modules/sanitize-html/dist/sanitize-html.js\");\n/* harmony import */ var sanitize_html__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(sanitize_html__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! react-draft-wysiwyg/dist/react-draft-wysiwyg.css */ \"./node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css\");\n/* harmony import */ var react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(react_draft_wysiwyg_dist_react_draft_wysiwyg_css__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var react_tooltip__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! react-tooltip */ \"./node_modules/react-tooltip/dist/index.es.js\");\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } }Line truncated
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
||||
Generated
+54
@@ -11830,6 +11830,55 @@
|
||||
"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": {
|
||||
"version": "10.0.0",
|
||||
"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",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"srcset": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/srcset/-/srcset-2.0.1.tgz",
|
||||
"integrity": "sha512-00kZI87TdRKwt+P8jj8UZxbfp7mK2ufxcIMWvhAOZNJTRROimpHeruWrGvCZneiuVDLqdyHefVp748ECTnyUBQ=="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
|
||||
+2
-1
@@ -17,7 +17,8 @@
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "^3.4.1",
|
||||
"react-select": "^3.1.0",
|
||||
"react-tooltip": "^4.2.7"
|
||||
"react-tooltip": "^4.2.7",
|
||||
"sanitize-html": "^1.27.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --mode development && mv dist/main.js ../js/admin.min.js"
|
||||
|
||||
+21
-79
@@ -3,11 +3,13 @@ import {Link} from "react-router-dom";
|
||||
import Alert from "../elements/alert";
|
||||
import {Collapse} from "react-collapse/lib/Collapse";
|
||||
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 draftToHtml from 'draftjs-to-html';
|
||||
import htmlToDraft from 'html-to-draftjs';
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
|
||||
import ReactTooltip from "react-tooltip";
|
||||
|
||||
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}>
|
||||
<label htmlFor={key}>
|
||||
{ title }
|
||||
<ReactTooltip id={"tooltip-" + key} />
|
||||
<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"}}
|
||||
onClick={() => this.closeEditor(true)}
|
||||
<Icon icon={"check"} className={"ml-2 text-success"} style={{cursor: "pointer"}}
|
||||
onClick={() => this.closeEditor(true)} data-type={"success"}
|
||||
data-tip={"Save Changes"} data-place={"top"} data-effect={"solid"}
|
||||
data-for={"tooltip-" + key}
|
||||
/>
|
||||
</label>
|
||||
{ editor }
|
||||
@@ -315,15 +322,16 @@ export default class Settings extends React.Component {
|
||||
} else {
|
||||
formGroups.push(
|
||||
<div className={"form-group"} key={"group-" + key}>
|
||||
<ReactTooltip id={"tooltip-" + key} />
|
||||
<label htmlFor={key}>
|
||||
{ title }
|
||||
<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>
|
||||
<textarea rows={6} className={"form-control"} disabled={true}
|
||||
value={this.state.settings[key] ?? ""} id={key} name={key}
|
||||
/>
|
||||
<div className={"p-2 text-black"} style={{backgroundColor: "#d2d6de"}} dangerouslySetInnerHTML={{ __html: sanitizeHtml(this.state.settings[key] ?? "") }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -332,77 +340,10 @@ export default class Settings extends React.Component {
|
||||
return formGroups;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
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>);
|
||||
}
|
||||
}
|
||||
getUncategorizedForm() {
|
||||
return <b>Coming soon…</b>
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
let errors = [];
|
||||
@@ -415,7 +356,7 @@ export default class Settings extends React.Component {
|
||||
"general": {color: "primary", icon: "cogs", title: "General Settings", content: this.createGeneralForm()},
|
||||
"mail": {color: "warning", icon: "envelope", title: "Mail Settings", content: this.createMailForm()},
|
||||
"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 = [];
|
||||
@@ -446,10 +387,11 @@ export default class Settings extends React.Component {
|
||||
{cards}
|
||||
</div>
|
||||
</div>
|
||||
<ReactTooltip />
|
||||
</>
|
||||
}
|
||||
|
||||
onEditorStateChange(editorState, key) {
|
||||
onEditorStateChange(editorState) {
|
||||
this.setState({
|
||||
...this.state,
|
||||
messages: {
|
||||
|
||||
Reference in new issue
Block a user