Added deleting of custom templates for BOD-85.
This commit is contained in:
@@ -218,6 +218,11 @@ function Header({
|
||||
<Menu.Item key='shop'>
|
||||
<Link to='/manage/shop'>{t("menus.header.shop_config")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='shop-templates'>
|
||||
<Link to='/manage/shop/templates'>
|
||||
{t("menus.header.shop_templates")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='shop-vendors'>
|
||||
<Link to='/manage/shop/vendors'>
|
||||
{t("menus.header.shop_vendors")}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { DownOutlined } from "@ant-design/icons";
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { Dropdown, Menu } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { INSERT_TEMPLATE } from "../../graphql/templates.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { TemplateList } from "../../utils/constants";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(ShopTemplateAddComponent);
|
||||
|
||||
export function ShopTemplateAddComponent({
|
||||
bodyshop,
|
||||
shopTemplateList,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const [insertTemplate] = useMutation(INSERT_TEMPLATE);
|
||||
|
||||
const shopTemplateKeys = shopTemplateList.map((template) => template.name);
|
||||
const availableTemplateKeys = Object.keys(TemplateList).filter(
|
||||
(tkey) => !shopTemplateKeys.includes(tkey)
|
||||
);
|
||||
|
||||
const handleAdd = async (item) => {
|
||||
const result = await insertTemplate({
|
||||
variables: {
|
||||
template: {
|
||||
name: item.key,
|
||||
bodyshopid: bodyshop.id,
|
||||
html: `<div>Insert your custom template here.</div>`,
|
||||
query: `query JOBS {
|
||||
jobs{
|
||||
id
|
||||
ro_number
|
||||
}
|
||||
}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const returningId = result.data.insert_templates.returning[0].id;
|
||||
search.customTemplateId = returningId;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
if (!!refetch) refetch();
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<Menu onClick={handleAdd}>
|
||||
{availableTemplateKeys.length > 0 ? (
|
||||
availableTemplateKeys.map((tkey) => (
|
||||
<Menu.Item key={tkey}>{TemplateList[tkey].title}</Menu.Item>
|
||||
))
|
||||
) : (
|
||||
<div>{t("bodyshop.labels.notemplatesavailable")}</div>
|
||||
)}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu}>
|
||||
<span>
|
||||
{t("bodyshop.actions.addtemplate")} <DownOutlined />
|
||||
</span>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { Button, notification, Popconfirm } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { DELETE_TEMPLATE } from "../../graphql/templates.queries";
|
||||
|
||||
export default function ShopTemplateDeleteComponent({ templateId, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const [deleteTemplate] = useMutation(DELETE_TEMPLATE);
|
||||
|
||||
const handleDelete = async () => {
|
||||
const result = await deleteTemplate({
|
||||
variables: {
|
||||
templateId: templateId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!!result.errors) {
|
||||
notification["error"]({
|
||||
message: t("bodyshop.errors.deletingtemplate", {
|
||||
message: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
delete search.customTemplateId;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
if (!!refetch) refetch();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Popconfirm
|
||||
title={t("general.labels.areyousure")}
|
||||
okText={t("general.labels.yes")}
|
||||
cancelText={t("general.labels.no")}
|
||||
onConfirm={handleDelete}>
|
||||
<Button>{t("general.actions.delete")}</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
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";
|
||||
|
||||
import { Input } from "antd";
|
||||
export default function ShopTemplateEditorComponent({
|
||||
templateId,
|
||||
html,
|
||||
@@ -11,14 +11,12 @@ export default function ShopTemplateEditorComponent({
|
||||
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 };
|
||||
});
|
||||
@@ -26,13 +24,11 @@ export default function ShopTemplateEditorComponent({
|
||||
|
||||
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
|
||||
@@ -55,37 +51,13 @@ export default function ShopTemplateEditorComponent({
|
||||
}
|
||||
/>
|
||||
QUERY
|
||||
<Editor
|
||||
<Input.TextArea
|
||||
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 })
|
||||
rows={8}
|
||||
onChange={(e) =>
|
||||
seteditorContent({ ...editorContent, gql: e.target.value })
|
||||
}
|
||||
/>
|
||||
</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());
|
||||
// }}
|
||||
// />
|
||||
|
||||
@@ -23,10 +23,11 @@ export default function ShopTemplateEditorContainer() {
|
||||
|
||||
return (
|
||||
<LoadingSpinner loading={loading}>
|
||||
{data && data.templates_by_pk ? data.templates_by_pk.name : ""}
|
||||
<ShopTemplateEditorComponent
|
||||
templateId={search.customTemplateId}
|
||||
html={data ? data.templates_by_pk.html : ""}
|
||||
gql={data ? data.templates_by_pk.query : ""}
|
||||
html={data && data.templates_by_pk ? data.templates_by_pk.html : ""}
|
||||
gql={data && data.templates_by_pk ? data.templates_by_pk.query : ""}
|
||||
editorState={editorState}
|
||||
/>
|
||||
</LoadingSpinner>
|
||||
|
||||
@@ -7,9 +7,12 @@ 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";
|
||||
import { TemplateList } from "../../utils/constants";
|
||||
import ShopTemplateAdd from "../shop-template-add/shop-template-add.component";
|
||||
import ShopTemplateDeleteComponent from "../shop-template-delete/shop-template-delete.component";
|
||||
|
||||
export default function ShopTemplatesListContainer() {
|
||||
const { loading, error, data } = useQuery(QUERY_CUSTOM_TEMPLATES);
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_CUSTOM_TEMPLATES);
|
||||
const { t } = useTranslation();
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
@@ -29,7 +32,11 @@ export default function ShopTemplatesListContainer() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>CUSTOM TEMPLATES</div>
|
||||
<div>{t("bodyshop.labels.customtemplates")}</div>
|
||||
<ShopTemplateAdd
|
||||
shopTemplateList={data ? data.templates : []}
|
||||
refetch={refetch}
|
||||
/>
|
||||
<List
|
||||
loading={loading}
|
||||
itemLayout='horizontal'
|
||||
@@ -40,12 +47,15 @@ export default function ShopTemplatesListContainer() {
|
||||
<Button onClick={() => handleEdit(item)}>
|
||||
{t("general.actions.edit")}
|
||||
</Button>,
|
||||
<Button>{t("general.actions.delete")}</Button>,
|
||||
<ShopTemplateDeleteComponent
|
||||
templateId={item.id}
|
||||
refetch={refetch}
|
||||
/>,
|
||||
]}>
|
||||
<Skeleton title={false} loading={item.loading} active>
|
||||
<List.Item.Meta
|
||||
title={item.name}
|
||||
description='TODO CROSS MATCH DESCRIPTION'
|
||||
title={TemplateList[item.name].title}
|
||||
description={TemplateList[item.name].description}
|
||||
/>
|
||||
</Skeleton>
|
||||
</List.Item>
|
||||
|
||||
Reference in New Issue
Block a user