diff --git a/client/public/editor.js b/client/public/editor.js
index 8fdef23aa..26893c6a1 100644
--- a/client/public/editor.js
+++ b/client/public/editor.js
@@ -1,112 +1,95 @@
-unlayer.registerPropertyEditor({
- name: "my_color_picker",
- layout: "bottom",
- Widget: unlayer.createWidget({
- render(value) {
- return `
-
-
-
-
- `;
- },
- mount(node, value, updateValue) {
- var input = node.getElementsByClassName("color-value")[0];
- input.onchange = function (event) {
- updateValue(event.target.value);
- };
+// unlayer.registerPropertyEditor({
+// name: "field_name",
+// layout: "bottom",
+// Widget: unlayer.createWidget({
+// render(value) {
+// return `
+//
+// `;
+// },
+// mount(node, value, updateValue) {
+// var input = node.getElementsByClassName("field")[0];
+// input.onchange = function (event) {
+// updateValue(event.target.value);
+// };
+// },
+// }),
+// });
- var redButton = node.getElementsByClassName("red")[0];
- redButton.onclick = function () {
- updateValue("#f00");
- };
+// unlayer.registerTool({
+// type: "whatever",
+// category: "contents",
+// label: "Begin Repeat",
+// icon: "fa-smile",
+// values: {},
+// options: {
+// default: {
+// title: null,
+// },
+// text: {
+// title: "Field",
+// position: 1,
+// options: {
+// field: {
+// label: "Field",
+// defaultValue: "",
+// widget: "field_name",
+// },
+// },
+// },
+// },
+// renderer: {
+// Viewer: unlayer.createViewer({
+// render(values) {
+// console.log(values);
+// return `
+//
{{#each ${values.field}}}
+// `;
+// },
+// }),
+// exporters: {
+// web: function () {},
+// email: function () {},
+// },
+// },
+// });
- var greenButton = node.getElementsByClassName("green")[0];
- greenButton.onclick = function () {
- updateValue("#0f0");
- };
-
- var blueButton = node.getElementsByClassName("blue")[0];
- blueButton.onclick = function () {
- updateValue("#00f");
- };
- },
- }),
-});
-
-unlayer.registerTool({
- type: "whatever",
- category: "contents",
- label: "My Tool",
- icon: "fa-smile",
- values: {},
- options: {
- default: {
- title: null,
- },
- text: {
- title: "Text",
- position: 1,
- options: {
- color: {
- label: "Color",
- defaultValue: "#000",
- widget: "my_color_picker",
- },
- },
- },
- },
- renderer: {
- Viewer: unlayer.createViewer({
- render(values) {
- return `
- I am a custom tool.
- `;
- },
- }),
- exporters: {
- web: function () {},
- email: function () {},
- },
- },
-});
+// unlayer.registerTool({
+// type: "whatever",
+// category: "contents",
+// label: "End Repeat",
+// icon: "fa-smile",
+// values: {},
+// options: {
+// default: {
+// title: null,
+// },
+// text: {
+// title: "Field",
+// position: 1,
+// options: {
+// field: {
+// label: "Field",
+// defaultValue: "",
+// widget: "field_name",
+// },
+// },
+// },
+// },
+// renderer: {
+// Viewer: unlayer.createViewer({
+// render(values) {
+// return `
+// {{ /each }}
+// `;
+// },
+// }),
+// exporters: {
+// web: function () {},
+// email: function () {},
+// },
+// },
+// });
unlayer.registerColumns([2, 2, 2, 2, 2, 2]);
unlayer.registerColumns([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
-
-unlayer.registerTool({
- type: "whatever",
- category: "contents",
- label: "Begin Repeater",
- icon: "fa-smile",
- values: {},
- options: {
- default: {
- title: "BeginRepeater",
- },
- text: {
- title: "Text",
- position: 1,
- options: {
- field: {
- label: "Field",
- defaultValue: "Field Name...",
- widget: "my_color_picker",
- },
- },
- },
- },
- renderer: {
- Viewer: unlayer.createViewer({
- render(values) {
- return `
- {{${values.field}}}
- `;
- },
- }),
- exporters: {
- web: function () {},
- email: function () {},
- },
- },
-});
diff --git a/client/public/render-styles.css b/client/public/render-styles.css
new file mode 100644
index 000000000..a58cf2b3f
--- /dev/null
+++ b/client/public/render-styles.css
@@ -0,0 +1,85 @@
+/* body {
+ font-family: "Open Sans", sans-serif;
+ line-height: 1.25;
+} */
+
+table {
+ border: 1px solid #ccc;
+ border-collapse: collapse;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ table-layout: fixed;
+}
+
+table caption {
+ font-size: 1.5em;
+ margin: 0.5em 0 0.75em;
+}
+
+table tr {
+ background-color: #f8f8f8;
+ border: 1px solid #ddd;
+ padding: 0.35em;
+}
+
+table th,
+table td {
+ padding: 0.625em;
+ text-align: center;
+}
+
+table th {
+ font-size: 0.85em;
+ letter-spacing: 0.1em;
+ text-transform: uppercase;
+}
+
+@media screen and (max-width: 600px) {
+ table {
+ border: 0;
+ }
+
+ table caption {
+ font-size: 1.3em;
+ }
+
+ table thead {
+ border: none;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ }
+
+ table tr {
+ border-bottom: 3px solid #ddd;
+ display: block;
+ margin-bottom: 0.625em;
+ }
+
+ table td {
+ border-bottom: 1px solid #ddd;
+ display: block;
+ font-size: 0.8em;
+ text-align: right;
+ }
+
+ table td::before {
+ /*
+ * aria-label has no advantage, it won't be read inside a table
+ content: attr(aria-label);
+ */
+ content: attr(data-label);
+ float: left;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+
+ table td:last-child {
+ border-bottom: 0;
+ }
+}
diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx
index 3d002b53e..e15528449 100644
--- a/client/src/App/App.container.jsx
+++ b/client/src/App/App.container.jsx
@@ -18,9 +18,25 @@ import App from "./App";
import { ConfigProvider } from "antd";
import enLocale from "antd/es/locale/en_US";
import moment from "moment";
+import axios from "axios";
moment.locale("en-US");
+axios.interceptors.request.use(
+ async (config) => {
+ if (!config.headers.Authorization) {
+ const token =
+ auth.currentUser && (await auth.currentUser.getIdToken(true));
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ }
+
+ return config;
+ },
+ (error) => Promise.reject(error)
+);
+
if (process.env.NODE_ENV === "production") LogRocket.init("gvfvfw/bodyshopapp");
const httpLink = new HttpLink({
diff --git a/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx b/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx
index bcd239c3f..bf94201fc 100644
--- a/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx
+++ b/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx
@@ -18,9 +18,11 @@ export default function ShopTemplateSaveButton({
logImEXEvent("shop_template_update");
emailEditorRef.current.exportHtml(async (data) => {
+ console.log("RAW", data.html);
inlineCss(data.html, {
- url: `${window.location.protocol}://${window.location.host}`,
+ url: `${window.location.protocol}://${window.location.host}/`,
}).then(async function (inlineHtml) {
+ console.log("Inline :>> ", inlineHtml);
const result = await updateTemplate({
variables: {
templateId: templateId,
diff --git a/client/src/components/shop-template-editor/shop-template-editor.component.jsx b/client/src/components/shop-template-editor/shop-template-editor.component.jsx
index e4e4c537a..367b1dbf9 100644
--- a/client/src/components/shop-template-editor/shop-template-editor.component.jsx
+++ b/client/src/components/shop-template-editor/shop-template-editor.component.jsx
@@ -14,8 +14,9 @@ export default function ShopTemplateEditorComponent({
const emailEditorRef = useRef(null);
useEffect(() => {
- if (json && Object.keys(json).length > 0)
+ if (json && Object.keys(json).length > 0 && emailEditorRef.current) {
emailEditorRef.current.loadDesign(json);
+ }
}, [json, emailEditorRef]);
useEffect(() => {
@@ -46,6 +47,12 @@ export default function ShopTemplateEditorComponent({
{
res.sendStatus(200);
};
+
+exports.validateFirebaseIdToken = async (req, res, next) => {
+ console.log("Check if request is authorized with Firebase ID token");
+
+ if (
+ (!req.headers.authorization ||
+ !req.headers.authorization.startsWith("Bearer ")) &&
+ !(req.cookies && req.cookies.__session)
+ ) {
+ console.error("Unauthorized attempt. No authorization provided.");
+ res.status(403).send("Unauthorized");
+ return;
+ }
+
+ let idToken;
+ if (
+ req.headers.authorization &&
+ req.headers.authorization.startsWith("Bearer ")
+ ) {
+ // console.log('Found "Authorization" header');
+ // Read the ID Token from the Authorization header.
+ idToken = req.headers.authorization.split("Bearer ")[1];
+ } else if (req.cookies) {
+ //console.log('Found "__session" cookie');
+ // Read the ID Token from cookie.
+ idToken = req.cookies.__session;
+ } else {
+ // No cookie
+ console.error("Unauthorized attempt. No cookie provided.");
+
+ res.status(403).send("Unauthorized");
+ return;
+ }
+
+ try {
+ const decodedIdToken = await admin.auth().verifyIdToken(idToken);
+ //console.log("ID Token correctly decoded", decodedIdToken);
+ req.user = decodedIdToken;
+ next();
+ return;
+ } catch (error) {
+ console.error("Error while verifying Firebase ID token:", error);
+ res.status(403).send("Unauthorized");
+ return;
+ }
+};