diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json
index 728cf33..797c43f 100644
--- a/dashboard/package-lock.json
+++ b/dashboard/package-lock.json
@@ -17,9 +17,6 @@
"@types/react-dom": "^17.0.11",
"@types/react-router-dom": "^5.3.2",
"dayjs": "^1.10.7",
- "draft-js": "^0.11.7",
- "draft-js-import-html": "^1.4.1",
- "draftjs-to-html": "^0.9.1",
"esbuild": "^0.14.9",
"focus-visible": "^5.2.0",
"framer-motion": "^5.5.5",
@@ -29,14 +26,14 @@
"react-dom": "^17.0.2",
"react-draft-wysiwyg": "^1.15.0",
"react-dropzone": "^12.0.4",
+ "react-email-editor": "^1.6.1",
"react-icons": "^4.3.1",
"react-router-dom": "^6.2.1",
"typescript": "^4.5.4",
"urql": "^2.0.6"
},
"devDependencies": {
- "@types/draftjs-to-html": "^0.8.1",
- "@types/react-draft-wysiwyg": "^1.13.4"
+ "@types/react-email-editor": "^1.1.7"
}
},
"node_modules/@babel/code-frame": {
@@ -1153,25 +1150,6 @@
"react-dom": "^16.8.0 || 17.x"
}
},
- "node_modules/@types/draft-js": {
- "version": "0.11.9",
- "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.9.tgz",
- "integrity": "sha512-cQJBZjjIlGaPA1tOY+wGz2KhlPtAAZOIXpUvGPxPRw5uzZ2tcj8m6Yu1QDV9YgP36+cqE3cUvgkARBzgUiuI/Q==",
- "dev": true,
- "dependencies": {
- "@types/react": "*",
- "immutable": "~3.7.4"
- }
- },
- "node_modules/@types/draftjs-to-html": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@types/draftjs-to-html/-/draftjs-to-html-0.8.1.tgz",
- "integrity": "sha512-NBkphQs+qZ/sAz/j1pCUaxkPAOx00LTsE88aMSSfcvK+UfCpjHJDqIMCkm6wKotuJvY5w0BtdRazQ0sAaXzPdg==",
- "dev": true,
- "dependencies": {
- "@types/draft-js": "*"
- }
- },
"node_modules/@types/history": {
"version": "4.7.9",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz",
@@ -1218,13 +1196,12 @@
"@types/react": "*"
}
},
- "node_modules/@types/react-draft-wysiwyg": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/@types/react-draft-wysiwyg/-/react-draft-wysiwyg-1.13.4.tgz",
- "integrity": "sha512-wasD1t78JDmQvdPDRPf/mf5FSHMlncunW0F6KMOKB3awzi3Wi21yHMGsRAUOkfTr3R8F+yceG8fSLz0kYWu/QA==",
+ "node_modules/@types/react-email-editor": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-email-editor/-/react-email-editor-1.1.7.tgz",
+ "integrity": "sha512-OURTAgaE9pjA6KiU97k13fPdoglI1ZyowUuZ0nu5tTSyrw5PiZoYzYEf9y25YTjmw/ohxT5yqoP0tt+AjSh1qQ==",
"dev": true,
"dependencies": {
- "@types/draft-js": "*",
"@types/react": "*"
}
},
@@ -1296,11 +1273,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
- "node_modules/asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
- },
"node_modules/attr-accept": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
@@ -1387,16 +1359,6 @@
"toggle-selection": "^1.0.6"
}
},
- "node_modules/core-js": {
- "version": "3.24.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
- "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==",
- "hasInstallScript": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
- }
- },
"node_modules/cosmiconfig": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -1412,14 +1374,6 @@
"node": ">=8"
}
},
- "node_modules/cross-fetch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
- "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
- "dependencies": {
- "node-fetch": "2.6.7"
- }
- },
"node_modules/css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
@@ -1448,59 +1402,6 @@
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
},
- "node_modules/draft-js": {
- "version": "0.11.7",
- "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz",
- "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==",
- "dependencies": {
- "fbjs": "^2.0.0",
- "immutable": "~3.7.4",
- "object-assign": "^4.1.1"
- },
- "peerDependencies": {
- "react": ">=0.14.0",
- "react-dom": ">=0.14.0"
- }
- },
- "node_modules/draft-js-import-element": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/draft-js-import-element/-/draft-js-import-element-1.4.0.tgz",
- "integrity": "sha512-WmYT5PrCm47lGL5FkH6sRO3TTAcn7qNHsD3igiPqLG/RXrqyKrqN4+wBgbcT2lhna/yfWTRtgzAbQsSJoS1Meg==",
- "dependencies": {
- "draft-js-utils": "^1.4.0",
- "synthetic-dom": "^1.4.0"
- },
- "peerDependencies": {
- "draft-js": ">=0.10.0",
- "immutable": "3.x.x"
- }
- },
- "node_modules/draft-js-import-html": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/draft-js-import-html/-/draft-js-import-html-1.4.1.tgz",
- "integrity": "sha512-KOZmtgxZriCDgg5Smr3Y09TjubvXe7rHPy/2fuLSsL+aSzwUDwH/aHDA/k47U+WfpmL4qgyg4oZhqx9TYJV0tg==",
- "dependencies": {
- "draft-js-import-element": "^1.4.0"
- },
- "peerDependencies": {
- "draft-js": ">=0.10.0",
- "immutable": "3.x.x"
- }
- },
- "node_modules/draft-js-utils": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/draft-js-utils/-/draft-js-utils-1.4.1.tgz",
- "integrity": "sha512-xE81Y+z/muC5D5z9qWmKfxEW1XyXfsBzSbSBk2JRsoD0yzMGGHQm/0MtuqHl/EUDkaBJJLjJ2EACycoDMY/OOg==",
- "peerDependencies": {
- "draft-js": ">=0.10.0",
- "immutable": "3.x.x"
- }
- },
- "node_modules/draftjs-to-html": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/draftjs-to-html/-/draftjs-to-html-0.9.1.tgz",
- "integrity": "sha512-fFstE6+IayaVFBEvaFt/wN8vdj8FsTRzij7dy7LI9QIwf5LgfHFi9zSpvCg+feJ2tbYVqHxUkjcibwpsTpgFVQ=="
- },
"node_modules/draftjs-utils": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.10.2.tgz",
@@ -1774,26 +1675,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/fbjs": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz",
- "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==",
- "dependencies": {
- "core-js": "^3.6.4",
- "cross-fetch": "^3.0.4",
- "fbjs-css-vars": "^1.0.0",
- "loose-envify": "^1.0.0",
- "object-assign": "^4.1.0",
- "promise": "^7.1.1",
- "setimmediate": "^1.0.5",
- "ua-parser-js": "^0.7.18"
- }
- },
- "node_modules/fbjs-css-vars": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
- "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
- },
"node_modules/file-selector": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.4.0.tgz",
@@ -1958,14 +1839,6 @@
"immutable": "3.x.x || 4.x.x"
}
},
- "node_modules/immutable": {
- "version": "3.7.6",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
- "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -2049,25 +1922,6 @@
"loose-envify": "cli.js"
}
},
- "node_modules/node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -2136,14 +1990,6 @@
"tslib": "^2.1.0"
}
},
- "node_modules/promise": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
- "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
- "dependencies": {
- "asap": "~2.0.3"
- }
- },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -2224,6 +2070,14 @@
"react": ">= 16.8"
}
},
+ "node_modules/react-email-editor": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/react-email-editor/-/react-email-editor-1.6.1.tgz",
+ "integrity": "sha512-pEWpRmTY0ok03cwTGqEOoEldnzThhuRGTrcMnv8W3/jc5MTfcr9USU/IQ9HrVvFStLKoxYBIQnSKY+iCYWOtSQ==",
+ "peerDependencies": {
+ "react": "15.x || 16.x || 17.x"
+ }
+ },
"node_modules/react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
@@ -2424,11 +2278,6 @@
"object-assign": "^4.1.1"
}
},
- "node_modules/setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
- },
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -2462,11 +2311,6 @@
"node": ">=4"
}
},
- "node_modules/synthetic-dom": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/synthetic-dom/-/synthetic-dom-1.4.0.tgz",
- "integrity": "sha512-mHv51ZsmZ+ShT/4s5kg+MGUIhY7Ltq4v03xpN1c8T1Krb5pScsh/lzEjyhrVD0soVDbThbd2e+4dD9vnDG4rhg=="
- },
"node_modules/tiny-invariant": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
@@ -2485,11 +2329,6 @@
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
"integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI="
},
- "node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
"node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
@@ -2507,24 +2346,6 @@
"node": ">=4.2.0"
}
},
- "node_modules/ua-parser-js": {
- "version": "0.7.31",
- "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
- "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- }
- ],
- "engines": {
- "node": "*"
- }
- },
"node_modules/uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
@@ -2588,20 +2409,6 @@
"loose-envify": "^1.0.0"
}
},
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
"node_modules/wonka": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz",
@@ -2798,8 +2605,7 @@
"@chakra-ui/css-reset": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
- "integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg==",
- "requires": {}
+ "integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg=="
},
"@chakra-ui/descendant": {
"version": "2.1.1",
@@ -3403,8 +3209,7 @@
"@graphql-typed-document-node/core": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
- "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
- "requires": {}
+ "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
},
"@popperjs/core": {
"version": "2.11.0",
@@ -3441,25 +3246,6 @@
"tslib": "^2.1.0"
}
},
- "@types/draft-js": {
- "version": "0.11.9",
- "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.9.tgz",
- "integrity": "sha512-cQJBZjjIlGaPA1tOY+wGz2KhlPtAAZOIXpUvGPxPRw5uzZ2tcj8m6Yu1QDV9YgP36+cqE3cUvgkARBzgUiuI/Q==",
- "dev": true,
- "requires": {
- "@types/react": "*",
- "immutable": "~3.7.4"
- }
- },
- "@types/draftjs-to-html": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@types/draftjs-to-html/-/draftjs-to-html-0.8.1.tgz",
- "integrity": "sha512-NBkphQs+qZ/sAz/j1pCUaxkPAOx00LTsE88aMSSfcvK+UfCpjHJDqIMCkm6wKotuJvY5w0BtdRazQ0sAaXzPdg==",
- "dev": true,
- "requires": {
- "@types/draft-js": "*"
- }
- },
"@types/history": {
"version": "4.7.9",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz",
@@ -3506,13 +3292,12 @@
"@types/react": "*"
}
},
- "@types/react-draft-wysiwyg": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/@types/react-draft-wysiwyg/-/react-draft-wysiwyg-1.13.4.tgz",
- "integrity": "sha512-wasD1t78JDmQvdPDRPf/mf5FSHMlncunW0F6KMOKB3awzi3Wi21yHMGsRAUOkfTr3R8F+yceG8fSLz0kYWu/QA==",
+ "@types/react-email-editor": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-email-editor/-/react-email-editor-1.1.7.tgz",
+ "integrity": "sha512-OURTAgaE9pjA6KiU97k13fPdoglI1ZyowUuZ0nu5tTSyrw5PiZoYzYEf9y25YTjmw/ohxT5yqoP0tt+AjSh1qQ==",
"dev": true,
"requires": {
- "@types/draft-js": "*",
"@types/react": "*"
}
},
@@ -3577,11 +3362,6 @@
}
}
},
- "asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
- },
"attr-accept": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
@@ -3658,11 +3438,6 @@
"toggle-selection": "^1.0.6"
}
},
- "core-js": {
- "version": "3.24.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
- "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg=="
- },
"cosmiconfig": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -3675,14 +3450,6 @@
"yaml": "^1.7.2"
}
},
- "cross-fetch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
- "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
- "requires": {
- "node-fetch": "2.6.7"
- }
- },
"css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
@@ -3711,49 +3478,10 @@
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
},
- "draft-js": {
- "version": "0.11.7",
- "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz",
- "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==",
- "requires": {
- "fbjs": "^2.0.0",
- "immutable": "~3.7.4",
- "object-assign": "^4.1.1"
- }
- },
- "draft-js-import-element": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/draft-js-import-element/-/draft-js-import-element-1.4.0.tgz",
- "integrity": "sha512-WmYT5PrCm47lGL5FkH6sRO3TTAcn7qNHsD3igiPqLG/RXrqyKrqN4+wBgbcT2lhna/yfWTRtgzAbQsSJoS1Meg==",
- "requires": {
- "draft-js-utils": "^1.4.0",
- "synthetic-dom": "^1.4.0"
- }
- },
- "draft-js-import-html": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/draft-js-import-html/-/draft-js-import-html-1.4.1.tgz",
- "integrity": "sha512-KOZmtgxZriCDgg5Smr3Y09TjubvXe7rHPy/2fuLSsL+aSzwUDwH/aHDA/k47U+WfpmL4qgyg4oZhqx9TYJV0tg==",
- "requires": {
- "draft-js-import-element": "^1.4.0"
- }
- },
- "draft-js-utils": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/draft-js-utils/-/draft-js-utils-1.4.1.tgz",
- "integrity": "sha512-xE81Y+z/muC5D5z9qWmKfxEW1XyXfsBzSbSBk2JRsoD0yzMGGHQm/0MtuqHl/EUDkaBJJLjJ2EACycoDMY/OOg==",
- "requires": {}
- },
- "draftjs-to-html": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/draftjs-to-html/-/draftjs-to-html-0.9.1.tgz",
- "integrity": "sha512-fFstE6+IayaVFBEvaFt/wN8vdj8FsTRzij7dy7LI9QIwf5LgfHFi9zSpvCg+feJ2tbYVqHxUkjcibwpsTpgFVQ=="
- },
"draftjs-utils": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.10.2.tgz",
- "integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg==",
- "requires": {}
+ "integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg=="
},
"error-ex": {
"version": "1.3.2",
@@ -3901,26 +3629,6 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
- "fbjs": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz",
- "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==",
- "requires": {
- "core-js": "^3.6.4",
- "cross-fetch": "^3.0.4",
- "fbjs-css-vars": "^1.0.0",
- "loose-envify": "^1.0.0",
- "object-assign": "^4.1.0",
- "promise": "^7.1.1",
- "setimmediate": "^1.0.5",
- "ua-parser-js": "^0.7.18"
- }
- },
- "fbjs-css-vars": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
- "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
- },
"file-selector": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.4.0.tgz",
@@ -4047,13 +3755,7 @@
"html-to-draftjs": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/html-to-draftjs/-/html-to-draftjs-1.5.0.tgz",
- "integrity": "sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ==",
- "requires": {}
- },
- "immutable": {
- "version": "3.7.6",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
- "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw=="
+ "integrity": "sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ=="
},
"import-fresh": {
"version": "3.3.0",
@@ -4126,14 +3828,6 @@
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
- "node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "requires": {
- "whatwg-url": "^5.0.0"
- }
- },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -4189,14 +3883,6 @@
}
}
},
- "promise": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
- "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
- "requires": {
- "asap": "~2.0.3"
- }
- },
"prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -4256,6 +3942,11 @@
"prop-types": "^15.8.1"
}
},
+ "react-email-editor": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/react-email-editor/-/react-email-editor-1.6.1.tgz",
+ "integrity": "sha512-pEWpRmTY0ok03cwTGqEOoEldnzThhuRGTrcMnv8W3/jc5MTfcr9USU/IQ9HrVvFStLKoxYBIQnSKY+iCYWOtSQ=="
+ },
"react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
@@ -4277,8 +3968,7 @@
"react-icons": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
- "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==",
- "requires": {}
+ "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
},
"react-is": {
"version": "16.13.1",
@@ -4400,11 +4090,6 @@
"object-assign": "^4.1.1"
}
},
- "setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
- },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -4432,11 +4117,6 @@
"has-flag": "^3.0.0"
}
},
- "synthetic-dom": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/synthetic-dom/-/synthetic-dom-1.4.0.tgz",
- "integrity": "sha512-mHv51ZsmZ+ShT/4s5kg+MGUIhY7Ltq4v03xpN1c8T1Krb5pScsh/lzEjyhrVD0soVDbThbd2e+4dD9vnDG4rhg=="
- },
"tiny-invariant": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
@@ -4452,11 +4132,6 @@
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
"integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI="
},
- "tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
@@ -4467,11 +4142,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg=="
},
- "ua-parser-js": {
- "version": "0.7.31",
- "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
- "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ=="
- },
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
@@ -4489,8 +4159,7 @@
"use-callback-ref": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
- "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
- "requires": {}
+ "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
},
"use-sidecar": {
"version": "1.0.5",
@@ -4516,20 +4185,6 @@
"loose-envify": "^1.0.0"
}
},
- "webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "requires": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
"wonka": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz",
diff --git a/dashboard/package.json b/dashboard/package.json
index bfb313e..5d23c3b 100644
--- a/dashboard/package.json
+++ b/dashboard/package.json
@@ -19,9 +19,6 @@
"@types/react-dom": "^17.0.11",
"@types/react-router-dom": "^5.3.2",
"dayjs": "^1.10.7",
- "draft-js": "^0.11.7",
- "draft-js-import-html": "^1.4.1",
- "draftjs-to-html": "^0.9.1",
"esbuild": "^0.14.9",
"focus-visible": "^5.2.0",
"framer-motion": "^5.5.5",
@@ -31,13 +28,13 @@
"react-dom": "^17.0.2",
"react-draft-wysiwyg": "^1.15.0",
"react-dropzone": "^12.0.4",
+ "react-email-editor": "^1.6.1",
"react-icons": "^4.3.1",
"react-router-dom": "^6.2.1",
"typescript": "^4.5.4",
"urql": "^2.0.6"
},
"devDependencies": {
- "@types/draftjs-to-html": "^0.8.1",
- "@types/react-draft-wysiwyg": "^1.13.4"
+ "@types/react-email-editor": "^1.1.7"
}
}
diff --git a/dashboard/src/components/EnvComponents/Features.tsx b/dashboard/src/components/EnvComponents/Features.tsx
index b106e70..095146d 100644
--- a/dashboard/src/components/EnvComponents/Features.tsx
+++ b/dashboard/src/components/EnvComponents/Features.tsx
@@ -83,6 +83,35 @@ const Features = ({ variables, setVariables }: any) => {
/>
+
+
+ Disable Multi Factor Authentication:
+
+
+
+
+
+
+
+ Enable Features
+
+
+
+
+ Enforce Multi Factor Authentication:
+
+
+
+
+
);
diff --git a/dashboard/src/components/UpdateEmailTemplateModal.tsx b/dashboard/src/components/UpdateEmailTemplateModal.tsx
index 1bb1690..e2d61c5 100644
--- a/dashboard/src/components/UpdateEmailTemplateModal.tsx
+++ b/dashboard/src/components/UpdateEmailTemplateModal.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import {
Button,
Center,
@@ -32,10 +32,7 @@ import {
} from '@chakra-ui/react';
import { FaPlus, FaAngleDown, FaAngleUp } from 'react-icons/fa';
import { useClient } from 'urql';
-import { Editor } from 'react-draft-wysiwyg';
-import { EditorState, convertToRaw, Modifier } from 'draft-js';
-import draftToHtml from 'draftjs-to-html';
-import { stateFromHTML } from 'draft-js-import-html';
+import EmailEditor from 'react-email-editor';
import {
UpdateModalViews,
EmailTemplateInputDataFields,
@@ -51,6 +48,7 @@ interface selectedEmailTemplateDataTypes {
[EmailTemplateInputDataFields.SUBJECT]: string;
[EmailTemplateInputDataFields.CREATED_AT]: number;
[EmailTemplateInputDataFields.TEMPLATE]: string;
+ [EmailTemplateInputDataFields.DESIGN]: string;
}
interface UpdateEmailTemplateInputPropTypes {
@@ -90,11 +88,9 @@ const UpdateEmailTemplate = ({
}: UpdateEmailTemplateInputPropTypes) => {
const client = useClient();
const toast = useToast();
+ const emailEditorRef = useRef(null);
const { isOpen, onOpen, onClose } = useDisclosure();
const [loading, setLoading] = useState(false);
- const [editorState, setEditorState] = React.useState(
- EditorState.createEmpty()
- );
const [templateVariables, setTemplateVariables] = useState<
templateVariableDataTypes[]
>([]);
@@ -104,12 +100,23 @@ const UpdateEmailTemplate = ({
const [validator, setValidator] = useState({
...initTemplateValidatorData,
});
- const onEditorStateChange = (editorState: EditorState) => {
- setEditorState(editorState);
- };
const [isDynamicVariableInfoOpen, setIsDynamicVariableInfoOpen] =
useState(false);
+ const onReady = () => {
+ if (selectedTemplate) {
+ const { design } = selectedTemplate;
+ try {
+ const designData = JSON.parse(design);
+ // @ts-ignore
+ emailEditorRef.current.editor.loadDesign(designData);
+ } catch (error) {
+ console.error(error);
+ onClose();
+ }
+ }
+ };
+
const inputChangehandler = (inputType: string, value: any) => {
if (inputType !== EmailTemplateInputDataFields.EVENT_NAME) {
setValidator({
@@ -121,14 +128,8 @@ const UpdateEmailTemplate = ({
};
const validateData = () => {
- const rawData: string = draftToHtml(
- convertToRaw(editorState.getCurrentContent())
- ).trim();
return (
!loading &&
- rawData &&
- rawData !== '' &&
- rawData !== '' &&
templateData[EmailTemplateInputDataFields.EVENT_NAME].length > 0 &&
templateData[EmailTemplateInputDataFields.SUBJECT].length > 0 &&
validator[EmailTemplateInputDataFields.SUBJECT]
@@ -138,69 +139,72 @@ const UpdateEmailTemplate = ({
const saveData = async () => {
if (!validateData()) return;
setLoading(true);
- const params = {
- [EmailTemplateInputDataFields.EVENT_NAME]:
- templateData[EmailTemplateInputDataFields.EVENT_NAME],
- [EmailTemplateInputDataFields.SUBJECT]:
- templateData[EmailTemplateInputDataFields.SUBJECT],
- [EmailTemplateInputDataFields.TEMPLATE]: draftToHtml(
- convertToRaw(editorState.getCurrentContent())
- ).trim(),
- };
- let res: any = {};
- if (
- view === UpdateModalViews.Edit &&
- selectedTemplate?.[EmailTemplateInputDataFields.ID]
- ) {
- res = await client
- .mutation(EditEmailTemplate, {
- params: {
- ...params,
- id: selectedTemplate[EmailTemplateInputDataFields.ID],
- },
- })
- .toPromise();
- } else {
- res = await client.mutation(AddEmailTemplate, { params }).toPromise();
- }
- setLoading(false);
- if (res.error) {
- toast({
- title: capitalizeFirstLetter(res.error.message),
- isClosable: true,
- status: 'error',
- position: 'bottom-right',
- });
- } else if (
- res.data?._add_email_template ||
- res.data?._update_email_template
- ) {
- toast({
- title: capitalizeFirstLetter(
- res.data?._add_email_template?.message ||
- res.data?._update_email_template?.message
- ),
- isClosable: true,
- status: 'success',
- position: 'bottom-right',
- });
- setTemplateData({
- ...initTemplateData,
- });
- setValidator({ ...initTemplateValidatorData });
- fetchEmailTemplatesData();
- }
- view === UpdateModalViews.ADD && onClose();
+ // @ts-ignore
+ return await emailEditorRef.current.editor.exportHtml(async (data) => {
+ const { design, html } = data;
+ if (!html || !design) {
+ setLoading(false);
+ return;
+ }
+ const params = {
+ [EmailTemplateInputDataFields.EVENT_NAME]:
+ templateData[EmailTemplateInputDataFields.EVENT_NAME],
+ [EmailTemplateInputDataFields.SUBJECT]:
+ templateData[EmailTemplateInputDataFields.SUBJECT],
+ [EmailTemplateInputDataFields.TEMPLATE]: html.trim(),
+ [EmailTemplateInputDataFields.DESIGN]: JSON.stringify(design),
+ };
+ let res: any = {};
+ if (
+ view === UpdateModalViews.Edit &&
+ selectedTemplate?.[EmailTemplateInputDataFields.ID]
+ ) {
+ res = await client
+ .mutation(EditEmailTemplate, {
+ params: {
+ ...params,
+ id: selectedTemplate[EmailTemplateInputDataFields.ID],
+ },
+ })
+ .toPromise();
+ } else {
+ res = await client.mutation(AddEmailTemplate, { params }).toPromise();
+ }
+ setLoading(false);
+ if (res.error) {
+ toast({
+ title: capitalizeFirstLetter(res.error.message),
+ isClosable: true,
+ status: 'error',
+ position: 'bottom-right',
+ });
+ } else if (
+ res.data?._add_email_template ||
+ res.data?._update_email_template
+ ) {
+ toast({
+ title: capitalizeFirstLetter(
+ res.data?._add_email_template?.message ||
+ res.data?._update_email_template?.message
+ ),
+ isClosable: true,
+ status: 'success',
+ position: 'bottom-right',
+ });
+ setTemplateData({
+ ...initTemplateData,
+ });
+ setValidator({ ...initTemplateValidatorData });
+ fetchEmailTemplatesData();
+ }
+ view === UpdateModalViews.ADD && onClose();
+ });
};
const resetData = () => {
if (selectedTemplate) {
setTemplateData(selectedTemplate);
- setEditorState(
- EditorState.createWithContent(stateFromHTML(selectedTemplate.template))
- );
} else {
setTemplateData({ ...initTemplateData });
- setEditorState(EditorState.createEmpty());
}
};
useEffect(() => {
@@ -210,9 +214,8 @@ const UpdateEmailTemplate = ({
selectedTemplate &&
Object.keys(selectedTemplate || {}).length
) {
- const { id, created_at, template, ...rest } = selectedTemplate;
+ const { id, created_at, template, design, ...rest } = selectedTemplate;
setTemplateData(rest);
- setEditorState(EditorState.createWithContent(stateFromHTML(template)));
}
}, [isOpen]);
useEffect(() => {
@@ -263,7 +266,7 @@ const UpdateEmailTemplate = ({
resetData();
onClose();
}}
- size="3xl"
+ size="6xl"
>
@@ -287,7 +290,7 @@ const UpdateEmailTemplate = ({
setIsDynamicVariableInfoOpen(!isDynamicVariableInfoOpen)
}
borderRadius="5"
- marginY={5}
+ marginBottom={5}
cursor="pointer"
fontSize="sm"
>
@@ -382,7 +385,7 @@ const UpdateEmailTemplate = ({
width="100%"
justifyContent="start"
alignItems="center"
- marginBottom="5%"
+ marginBottom="2%"
>
Subject
@@ -407,41 +410,21 @@ const UpdateEmailTemplate = ({
- Template Body
- {`To select dynamic variables open curly braces "{"`}
+ Template Body
+
+
+
-
-
-
-
- Note: In order to use dynamic variables with link and
- images you can put them as part of URL in editor section.
-
-
diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts
index 95d7248..db7a964 100644
--- a/dashboard/src/constants.ts
+++ b/dashboard/src/constants.ts
@@ -68,6 +68,8 @@ export const SwitchInputType = {
DISABLE_SIGN_UP: 'DISABLE_SIGN_UP',
DISABLE_REDIS_FOR_ENV: 'DISABLE_REDIS_FOR_ENV',
DISABLE_STRONG_PASSWORD: 'DISABLE_STRONG_PASSWORD',
+ DISABLE_MULTI_FACTOR_AUTHENTICATION: 'DISABLE_MULTI_FACTOR_AUTHENTICATION',
+ ENFORCE_MULTI_FACTOR_AUTHENTICATION: 'ENFORCE_MULTI_FACTOR_AUTHENTICATION',
};
export const DateInputType = {
@@ -138,6 +140,8 @@ export interface envVarTypes {
DATABASE_TYPE: string;
DATABASE_URL: string;
ACCESS_TOKEN_EXPIRY_TIME: string;
+ DISABLE_MULTI_FACTOR_AUTHENTICATION: boolean;
+ ENFORCE_MULTI_FACTOR_AUTHENTICATION: boolean;
}
export const envSubViews = {
@@ -168,6 +172,7 @@ export enum EmailTemplateInputDataFields {
SUBJECT = 'subject',
CREATED_AT = 'created_at',
TEMPLATE = 'template',
+ DESIGN = 'design',
}
export enum WebhookInputHeaderFields {
diff --git a/dashboard/src/graphql/queries/index.ts b/dashboard/src/graphql/queries/index.ts
index 146748b..0d073ee 100644
--- a/dashboard/src/graphql/queries/index.ts
+++ b/dashboard/src/graphql/queries/index.ts
@@ -60,6 +60,8 @@ export const EnvVariablesQuery = `
DATABASE_TYPE,
DATABASE_URL,
ACCESS_TOKEN_EXPIRY_TIME,
+ DISABLE_MULTI_FACTOR_AUTHENTICATION,
+ ENFORCE_MULTI_FACTOR_AUTHENTICATION,
}
}
`;
@@ -132,6 +134,7 @@ export const EmailTemplatesQuery = `
subject
created_at
template
+ design
}
pagination {
limit
diff --git a/dashboard/src/pages/EmailTemplates.tsx b/dashboard/src/pages/EmailTemplates.tsx
index 83bea54..cccd1be 100644
--- a/dashboard/src/pages/EmailTemplates.tsx
+++ b/dashboard/src/pages/EmailTemplates.tsx
@@ -58,6 +58,7 @@ interface EmailTemplateDataType {
[EmailTemplateInputDataFields.SUBJECT]: string;
[EmailTemplateInputDataFields.CREATED_AT]: number;
[EmailTemplateInputDataFields.TEMPLATE]: string;
+ [EmailTemplateInputDataFields.DESIGN]: string;
}
const EmailTemplates = () => {
diff --git a/dashboard/src/pages/Environment.tsx b/dashboard/src/pages/Environment.tsx
index 7b14de8..e9eafc8 100644
--- a/dashboard/src/pages/Environment.tsx
+++ b/dashboard/src/pages/Environment.tsx
@@ -80,6 +80,8 @@ const Environment = () => {
DATABASE_TYPE: '',
DATABASE_URL: '',
ACCESS_TOKEN_EXPIRY_TIME: '',
+ DISABLE_MULTI_FACTOR_AUTHENTICATION: false,
+ ENFORCE_MULTI_FACTOR_AUTHENTICATION: false,
});
const [fieldVisibility, setFieldVisibility] = React.useState<
diff --git a/server/db/models/email_templates.go b/server/db/models/email_templates.go
index 8c6de30..210848e 100644
--- a/server/db/models/email_templates.go
+++ b/server/db/models/email_templates.go
@@ -14,6 +14,7 @@ type EmailTemplate struct {
EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"`
Subject string `gorm:"type:text" json:"subject" bson:"subject" cql:"subject"`
Template string `gorm:"type:text" json:"template" bson:"template" cql:"template"`
+ Design string `gorm:"type:text" json:"design" bson:"design" cql:"design"`
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
}
@@ -29,6 +30,7 @@ func (e *EmailTemplate) AsAPIEmailTemplate() *model.EmailTemplate {
EventName: e.EventName,
Subject: e.Subject,
Template: e.Template,
+ Design: e.Design,
CreatedAt: refs.NewInt64Ref(e.CreatedAt),
UpdatedAt: refs.NewInt64Ref(e.UpdatedAt),
}
diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go
index d7cc5c6..e5b3d7d 100644
--- a/server/graph/generated/generated.go
+++ b/server/graph/generated/generated.go
@@ -55,6 +55,7 @@ type ComplexityRoot struct {
EmailTemplate struct {
CreatedAt func(childComplexity int) int
+ Design func(childComplexity int) int
EventName func(childComplexity int) int
ID func(childComplexity int) int
Subject func(childComplexity int) int
@@ -406,6 +407,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.EmailTemplate.CreatedAt(childComplexity), true
+ case "EmailTemplate.design":
+ if e.complexity.EmailTemplate.Design == nil {
+ break
+ }
+
+ return e.complexity.EmailTemplate.Design(childComplexity), true
+
case "EmailTemplate.event_name":
if e.complexity.EmailTemplate.EventName == nil {
break
@@ -2059,6 +2067,7 @@ type EmailTemplate {
id: ID!
event_name: String!
template: String!
+ design: String!
subject: String!
created_at: Int64
updated_at: Int64
@@ -2282,6 +2291,7 @@ input AddEmailTemplateRequest {
event_name: String!
subject: String!
template: String!
+ design: String!
}
input UpdateEmailTemplateRequest {
@@ -2289,6 +2299,7 @@ input UpdateEmailTemplateRequest {
event_name: String
template: String
subject: String
+ design: String
}
input DeleteEmailTemplateRequest {
@@ -3270,6 +3281,41 @@ func (ec *executionContext) _EmailTemplate_template(ctx context.Context, field g
return ec.marshalNString2string(ctx, field.Selections, res)
}
+func (ec *executionContext) _EmailTemplate_design(ctx context.Context, field graphql.CollectedField, obj *model.EmailTemplate) (ret graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ fc := &graphql.FieldContext{
+ Object: "EmailTemplate",
+ Field: field,
+ Args: nil,
+ IsMethod: false,
+ IsResolver: false,
+ }
+
+ ctx = graphql.WithFieldContext(ctx, fc)
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Design, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ if !graphql.HasFieldError(ctx, fc) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
func (ec *executionContext) _EmailTemplate_subject(ctx context.Context, field graphql.CollectedField, obj *model.EmailTemplate) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@@ -10521,6 +10567,14 @@ func (ec *executionContext) unmarshalInputAddEmailTemplateRequest(ctx context.Co
if err != nil {
return it, err
}
+ case "design":
+ var err error
+
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("design"))
+ it.Design, err = ec.unmarshalNString2string(ctx, v)
+ if err != nil {
+ return it, err
+ }
}
}
@@ -11331,6 +11385,14 @@ func (ec *executionContext) unmarshalInputUpdateEmailTemplateRequest(ctx context
if err != nil {
return it, err
}
+ case "design":
+ var err error
+
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("design"))
+ it.Design, err = ec.unmarshalOString2áš–string(ctx, v)
+ if err != nil {
+ return it, err
+ }
}
}
@@ -12162,6 +12224,11 @@ func (ec *executionContext) _EmailTemplate(ctx context.Context, sel ast.Selectio
if out.Values[i] == graphql.Null {
invalids++
}
+ case "design":
+ out.Values[i] = ec._EmailTemplate_design(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalids++
+ }
case "subject":
out.Values[i] = ec._EmailTemplate_subject(ctx, field, obj)
if out.Values[i] == graphql.Null {
diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go
index 86a4a0c..f4f125f 100644
--- a/server/graph/model/models_gen.go
+++ b/server/graph/model/models_gen.go
@@ -6,6 +6,7 @@ type AddEmailTemplateRequest struct {
EventName string `json:"event_name"`
Subject string `json:"subject"`
Template string `json:"template"`
+ Design string `json:"design"`
}
type AddWebhookRequest struct {
@@ -45,6 +46,7 @@ type EmailTemplate struct {
ID string `json:"id"`
EventName string `json:"event_name"`
Template string `json:"template"`
+ Design string `json:"design"`
Subject string `json:"subject"`
CreatedAt *int64 `json:"created_at"`
UpdatedAt *int64 `json:"updated_at"`
@@ -252,6 +254,7 @@ type UpdateEmailTemplateRequest struct {
EventName *string `json:"event_name"`
Template *string `json:"template"`
Subject *string `json:"subject"`
+ Design *string `json:"design"`
}
type UpdateEnvInput struct {
diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls
index cbfd9e1..425be3c 100644
--- a/server/graph/schema.graphqls
+++ b/server/graph/schema.graphqls
@@ -194,6 +194,7 @@ type EmailTemplate {
id: ID!
event_name: String!
template: String!
+ design: String!
subject: String!
created_at: Int64
updated_at: Int64
@@ -417,6 +418,7 @@ input AddEmailTemplateRequest {
event_name: String!
subject: String!
template: String!
+ design: String!
}
input UpdateEmailTemplateRequest {
@@ -424,6 +426,7 @@ input UpdateEmailTemplateRequest {
event_name: String
template: String
subject: String
+ design: String
}
input DeleteEmailTemplateRequest {
diff --git a/server/resolvers/add_email_template.go b/server/resolvers/add_email_template.go
index 5b53d60..e5a1dc2 100644
--- a/server/resolvers/add_email_template.go
+++ b/server/resolvers/add_email_template.go
@@ -40,10 +40,15 @@ func AddEmailTemplateResolver(ctx context.Context, params model.AddEmailTemplate
return nil, fmt.Errorf("empty template not allowed")
}
+ if strings.TrimSpace(params.Design) == "" {
+ return nil, fmt.Errorf("empty design not allowed")
+ }
+
_, err = db.Provider.AddEmailTemplate(ctx, models.EmailTemplate{
EventName: params.EventName,
Template: params.Template,
Subject: params.Subject,
+ Design: params.Design,
})
if err != nil {
log.Debug("Failed to add email template: ", err)
diff --git a/server/resolvers/update_email_template.go b/server/resolvers/update_email_template.go
index f0ab2b8..cf4e948 100644
--- a/server/resolvers/update_email_template.go
+++ b/server/resolvers/update_email_template.go
@@ -65,6 +65,14 @@ func UpdateEmailTemplateResolver(ctx context.Context, params model.UpdateEmailTe
emailTemplateDetails.Template = refs.StringValue(params.Template)
}
+ if params.Design != nil && emailTemplateDetails.Design != refs.StringValue(params.Design) {
+ if strings.TrimSpace(refs.StringValue(params.Design)) == "" {
+ log.Debug("empty design not allowed")
+ return nil, fmt.Errorf("empty design not allowed")
+ }
+ emailTemplateDetails.Design = refs.StringValue(params.Design)
+ }
+
_, err = db.Provider.UpdateEmailTemplate(ctx, emailTemplateDetails)
if err != nil {
return nil, err