Added basic pages for template editing BOD-85
This commit is contained in:
@@ -3,7 +3,7 @@ import axios from "axios";
|
||||
import React, { useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { EmailSettings } from "../../emails/constants";
|
||||
import { EmailSettings } from "../../utils/constants";
|
||||
import {
|
||||
endLoading,
|
||||
startLoading,
|
||||
|
||||
@@ -5,7 +5,7 @@ import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { EmailSettings } from "../../emails/constants";
|
||||
import { EmailSettings } from "../../utils/constants";
|
||||
import { toggleEmailOverlayVisible } from "../../redux/email/email.actions";
|
||||
import {
|
||||
selectEmailConfig,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { Button, notification } from "antd";
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { UPDATE_TEMPLATE } from "../../graphql/templates.queries";
|
||||
|
||||
export default function ShopTemplateSaveButton({ templateId, html, gql }) {
|
||||
const { t } = useTranslation();
|
||||
const [updateTemplate] = useMutation(UPDATE_TEMPLATE);
|
||||
|
||||
const handleSave = async () => {
|
||||
const result = await updateTemplate({
|
||||
variables: {
|
||||
templateId: templateId,
|
||||
template: { query: gql, html },
|
||||
},
|
||||
});
|
||||
if (!!!result.errors) {
|
||||
notification["success"]({ message: t("templates.successes.updated") });
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("templates.errors.updating", {
|
||||
error: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Button disabled={!!!templateId} onClick={handleSave}>
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { Editor } from "@tinymce/tinymce-react";
|
||||
import React, { useEffect } from "react";
|
||||
import ShopTemplateEditorSaveButton from "../shop-template-editor-save-button/shop-template-editor-save-button.component";
|
||||
|
||||
export default function ShopTemplateEditorComponent({
|
||||
templateId,
|
||||
html,
|
||||
gql,
|
||||
editorState,
|
||||
}) {
|
||||
const [editorContent, seteditorContent] = editorState;
|
||||
|
||||
useEffect(() => {
|
||||
console.log("HTML UE");
|
||||
seteditorContent((prevstate) => {
|
||||
return { ...prevstate, html: html };
|
||||
});
|
||||
}, [html, seteditorContent]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("gql UE");
|
||||
seteditorContent((prevstate) => {
|
||||
return { ...prevstate, gql: gql };
|
||||
});
|
||||
}, [gql, seteditorContent]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
Editor Here. template Editor
|
||||
<ShopTemplateEditorSaveButton
|
||||
templateId={templateId}
|
||||
html={editorContent.html}
|
||||
gql={editorContent.gql}
|
||||
/>
|
||||
TEMPLATE
|
||||
<Editor
|
||||
value={editorContent.html}
|
||||
apiKey='f3s2mjsd77ya5qvqkee9vgh612cm6h41e85efqakn2d0kknk' //TODO Pull this into app var
|
||||
init={{
|
||||
height: 500,
|
||||
//menubar: false,
|
||||
encoding: "raw",
|
||||
extended_valid_elements: "span",
|
||||
//entity_encoding: "raw",
|
||||
plugins: [
|
||||
"advlist autolink lists link image charmap print preview anchor",
|
||||
"searchreplace visualblocks code fullscreen",
|
||||
"insertdatetime media table paste code help wordcount",
|
||||
],
|
||||
toolbar:
|
||||
"undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help",
|
||||
}}
|
||||
onEditorChange={(text) =>
|
||||
seteditorContent({ ...editorContent, html: text })
|
||||
}
|
||||
/>
|
||||
QUERY
|
||||
<Editor
|
||||
value={editorContent.gql}
|
||||
apiKey='f3s2mjsd77ya5qvqkee9vgh612cm6h41e85efqakn2d0kknk' //TODO Pull this into app var
|
||||
init={{
|
||||
height: 500,
|
||||
//menubar: false,
|
||||
encoding: "raw",
|
||||
extended_valid_elements: "span",
|
||||
//entity_encoding: "raw",
|
||||
plugins: [],
|
||||
toolbar: "undo redo",
|
||||
}}
|
||||
onEditorChange={(text) =>
|
||||
seteditorContent({ ...editorContent, gql: text })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// <GraphiQL
|
||||
// fetcher={async (graphQLParams) => {
|
||||
// const data = await fetch(process.env.REACT_APP_GRAPHQL_ENDPOINT, {
|
||||
// method: "POST",
|
||||
// headers: {
|
||||
// Accept: "application/json",
|
||||
// "Content-Type": "application/json",
|
||||
// },
|
||||
// body: JSON.stringify(graphQLParams),
|
||||
// credentials: "same-origin",
|
||||
// });
|
||||
// return data.json().catch(() => data.text());
|
||||
// }}
|
||||
// />
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useQuery } from "@apollo/react-hooks";
|
||||
import queryString from "query-string";
|
||||
import React, { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { QUERY_TEMPLATE_BY_PK } from "../../graphql/templates.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import ShopTemplateEditorComponent from "./shop-template-editor.component";
|
||||
|
||||
export default function ShopTemplateEditorContainer() {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const editorState = useState({ html: "", gql: "" });
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_TEMPLATE_BY_PK, {
|
||||
variables: {
|
||||
templateId: search.customTemplateId,
|
||||
},
|
||||
skip: !!!search.customTemplateId,
|
||||
});
|
||||
|
||||
if (!!!search.customTemplateId) return <span>No selection.</span>;
|
||||
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||
|
||||
return (
|
||||
<LoadingSpinner loading={loading}>
|
||||
<ShopTemplateEditorComponent
|
||||
templateId={search.customTemplateId}
|
||||
html={data ? data.templates_by_pk.html : ""}
|
||||
gql={data ? data.templates_by_pk.query : ""}
|
||||
editorState={editorState}
|
||||
/>
|
||||
</LoadingSpinner>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { useQuery } from "@apollo/react-hooks";
|
||||
import { List, Button } from "antd";
|
||||
import React from "react";
|
||||
import { QUERY_CUSTOM_TEMPLATES } from "../../graphql/templates.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import Skeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import queryString from "query-string";
|
||||
|
||||
export default function ShopTemplatesListContainer() {
|
||||
const { loading, error, data } = useQuery(QUERY_CUSTOM_TEMPLATES);
|
||||
const { t } = useTranslation();
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||
|
||||
const handleEdit = (record) => {
|
||||
if (record) {
|
||||
if (record.id) {
|
||||
search.customTemplateId = record.id;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}
|
||||
} else {
|
||||
delete search.customTemplateId;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>CUSTOM TEMPLATES</div>
|
||||
<List
|
||||
loading={loading}
|
||||
itemLayout='horizontal'
|
||||
dataSource={data ? data.templates : []}
|
||||
renderItem={(item) => (
|
||||
<List.Item
|
||||
actions={[
|
||||
<Button onClick={() => handleEdit(item)}>
|
||||
{t("general.actions.edit")}
|
||||
</Button>,
|
||||
<Button>{t("general.actions.delete")}</Button>,
|
||||
]}>
|
||||
<Skeleton title={false} loading={item.loading} active>
|
||||
<List.Item.Meta
|
||||
title={item.name}
|
||||
description='TODO CROSS MATCH DESCRIPTION'
|
||||
/>
|
||||
</Skeleton>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user