Added deleting of custom templates for BOD-85.

This commit is contained in:
Patrick Fic
2020-05-12 10:25:36 -07:00
parent b518f84f5f
commit 6fd485c2fe
21 changed files with 770 additions and 307 deletions

View File

@@ -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")}

View File

@@ -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>
);
}

View File

@@ -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>
);
}

View File

@@ -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());
// }}
// />

View File

@@ -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>

View File

@@ -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>