Added new HTML editor with some breaking changes.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<babeledit_project version="1.2" be_version="2.7.1">
|
||||
<babeledit_project be_version="2.7.1" version="1.2">
|
||||
<!--
|
||||
|
||||
BabelEdit project file
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"react-big-calendar": "^0.26.0",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-drag-listview": "^0.1.7",
|
||||
"react-email-editor": "^1.1.1",
|
||||
"react-ga": "^3.1.2",
|
||||
"react-grid-gallery": "^0.5.5",
|
||||
"react-grid-layout": "^1.0.0",
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function FormsFieldChanged({ form }) {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return null;
|
||||
return <div style={{ display: "none" }}></div>;
|
||||
}}
|
||||
</Form.Item>
|
||||
);
|
||||
|
||||
@@ -6,13 +6,23 @@ import Icon, {
|
||||
FileFilled,
|
||||
GlobalOutlined,
|
||||
HomeFilled,
|
||||
ImportOutlined,
|
||||
LineChartOutlined,
|
||||
ScheduleOutlined,
|
||||
TeamOutlined,
|
||||
UnorderedListOutlined,
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Avatar, Col, Layout, Menu, Row } from "antd";
|
||||
import { Avatar, Layout, Menu } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaCalendarAlt, FaCarCrash, FaCreditCard } from "react-icons/fa";
|
||||
import { BsKanban } from "react-icons/bs";
|
||||
import {
|
||||
FaCalendarAlt,
|
||||
FaCarCrash,
|
||||
FaCreditCard,
|
||||
FaFileInvoiceDollar,
|
||||
} from "react-icons/fa";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
@@ -42,30 +52,6 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
signOutStart: () => dispatch(signOutStart()),
|
||||
});
|
||||
|
||||
const logoSpan = {
|
||||
xs: {
|
||||
span: 0,
|
||||
},
|
||||
sm: { span: 0 },
|
||||
md: {
|
||||
span: 0,
|
||||
},
|
||||
lg: {
|
||||
span: 2,
|
||||
},
|
||||
};
|
||||
|
||||
const menuSpan = {
|
||||
md: {
|
||||
span: 24,
|
||||
//offset: 1,
|
||||
},
|
||||
lg: {
|
||||
span: 21,
|
||||
offset: 1,
|
||||
},
|
||||
};
|
||||
|
||||
function Header({
|
||||
bodyshop,
|
||||
handleMenuClick,
|
||||
@@ -81,280 +67,276 @@ function Header({
|
||||
|
||||
return (
|
||||
<Header>
|
||||
<Row>
|
||||
<Col {...logoSpan}>
|
||||
<img
|
||||
className="header-shop-logo"
|
||||
alt={bodyshop ? bodyshop.shopname : "ImEX Online Logo"}
|
||||
src={
|
||||
bodyshop && bodyshop.logo_img_path
|
||||
? bodyshop.logo_img_path
|
||||
: "./logo192.png"
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
<Col {...menuSpan}>
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
theme="dark"
|
||||
className="header-main-menu"
|
||||
selectedKeys={["home"]}
|
||||
onClick={handleMenuClick}
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
theme="dark"
|
||||
className="header-main-menu"
|
||||
selectedKeys={["home"]}
|
||||
onClick={handleMenuClick}
|
||||
>
|
||||
<Menu.Item key="home">
|
||||
<Link to="/manage">
|
||||
<HomeFilled />
|
||||
{t("menus.header.home")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="schedule">
|
||||
<Link to="/manage/schedule">
|
||||
<Icon component={FaCalendarAlt} />
|
||||
{t("menus.header.schedule")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon component={FaCarCrash} />
|
||||
<span>{t("menus.header.jobs")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="activejobs">
|
||||
<FileFilled />
|
||||
<Link to="/manage/jobs">{t("menus.header.activejobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="availablejobs">
|
||||
<Link to="/manage/available">
|
||||
<ImportOutlined /> {t("menus.header.availablejobs")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="alljobs">
|
||||
<UnorderedListOutlined />
|
||||
<Link to="/manage/jobs/all">{t("menus.header.alljobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.Item key="productionlist">
|
||||
<Link to="/manage/production/list">
|
||||
<ScheduleOutlined />
|
||||
{t("menus.header.productionlist")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="productionboard">
|
||||
<Link to="/manage/production/board">
|
||||
<Icon component={BsKanban} />
|
||||
{t("menus.header.productionboard")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.Item key="scoreboard">
|
||||
<LineChartOutlined />
|
||||
<Link to="/manage/scoreboard">{t("menus.header.scoreboard")}</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<UserOutlined />
|
||||
<span>{t("menus.header.customers")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="owners">
|
||||
<Link to="/manage/owners">
|
||||
<TeamOutlined />
|
||||
{t("menus.header.owners")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="vehicles">
|
||||
<Link to="/manage/vehicles">
|
||||
<CarFilled />
|
||||
{t("menus.header.vehicles")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<CarFilled />
|
||||
<span>{t("menus.header.courtesycars")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="courtesycarsall">
|
||||
<Link to="/manage/courtesycars">
|
||||
<CarFilled />
|
||||
{t("menus.header.courtesycars-all")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="contracts">
|
||||
<Link to="/manage/courtesycars/contracts">
|
||||
<FileFilled />
|
||||
{t("menus.header.courtesycars-contracts")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="newcontract">
|
||||
<Link to="/manage/courtesycars/contracts/new">
|
||||
<FileAddFilled />
|
||||
{t("menus.header.courtesycars-newcontract")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<DollarCircleFilled />
|
||||
<span>{t("menus.header.accounting")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="invoices">
|
||||
<Link to="/manage/invoices">{t("menus.header.invoices")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="enterinvoices"
|
||||
onClick={() => {
|
||||
setInvoiceEnterContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Menu.Item key="home">
|
||||
<Link to="/manage">
|
||||
<HomeFilled />
|
||||
{t("menus.header.home")}
|
||||
<Icon component={FaFileInvoiceDollar} />
|
||||
{t("menus.header.enterinvoices")}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="allpayments">
|
||||
<Link to="/manage/payments">{t("menus.header.allpayments")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="enterpayments"
|
||||
onClick={() => {
|
||||
setPaymentContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon component={FaCreditCard} />
|
||||
{t("menus.header.enterpayment")}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.Item key="timetickets">
|
||||
<Link to="/manage/timetickets">
|
||||
{t("menus.header.timetickets")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="entertimetickets"
|
||||
onClick={() => {
|
||||
setTimeTicketContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("menus.header.entertimeticket")}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.SubMenu title={t("menus.header.export")}>
|
||||
<Menu.Item key="receivables">
|
||||
<Link to="/manage/accounting/receivables">
|
||||
{t("menus.header.accounting-receivables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon component={FaCarCrash} />
|
||||
<span>{t("menus.header.jobs")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="schedule">
|
||||
<Link to="/manage/schedule">
|
||||
<Icon component={FaCalendarAlt} />
|
||||
{t("menus.header.schedule")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="productionlist">
|
||||
<Link to="/manage/production/list">
|
||||
<Icon component={FaCalendarAlt} />
|
||||
{t("menus.header.productionlist")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="productionboard">
|
||||
<Link to="/manage/production/board">
|
||||
{t("menus.header.productionboard")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="scoreboard">
|
||||
<Link to="/manage/scoreboard">
|
||||
{t("menus.header.scoreboard")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="activejobs">
|
||||
<Link to="/manage/jobs">{t("menus.header.activejobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="alljobs">
|
||||
<Link to="/manage/jobs/all">{t("menus.header.alljobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="availablejobs">
|
||||
<Link to="/manage/available">
|
||||
{t("menus.header.availablejobs")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu title={t("menus.header.customers")}>
|
||||
<Menu.Item key="owners">
|
||||
<Link to="/manage/owners">
|
||||
<TeamOutlined />
|
||||
{t("menus.header.owners")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="vehicles">
|
||||
<Link to="/manage/vehicles">
|
||||
<CarFilled />
|
||||
{t("menus.header.vehicles")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<CarFilled />
|
||||
<span>{t("menus.header.courtesycars")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="courtesycarsall">
|
||||
<Link to="/manage/courtesycars">
|
||||
<CarFilled />
|
||||
{t("menus.header.courtesycars-all")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="contracts">
|
||||
<Link to="/manage/courtesycars/contracts">
|
||||
<FileFilled />
|
||||
{t("menus.header.courtesycars-contracts")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="newcontract">
|
||||
<Link to="/manage/courtesycars/contracts/new">
|
||||
<FileAddFilled />
|
||||
{t("menus.header.courtesycars-newcontract")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<DollarCircleFilled />
|
||||
<span>{t("menus.header.accounting")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item
|
||||
key="enterpayments"
|
||||
onClick={() => {
|
||||
setPaymentContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon component={FaCreditCard} />
|
||||
{t("menus.header.enterpayment")}
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
key="enterinvoices"
|
||||
onClick={() => {
|
||||
setInvoiceEnterContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("menus.header.enterinvoices")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="invoices">
|
||||
<Link to="/manage/invoices">{t("menus.header.invoices")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="timetickets">
|
||||
<Link to="/manage/timetickets">
|
||||
{t("menus.header.timetickets")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key="entertimetickets"
|
||||
onClick={() => {
|
||||
setTimeTicketContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("menus.header.entertimeticket")}
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.SubMenu title={t("menus.header.export")}>
|
||||
<Menu.Item key="receivables">
|
||||
<Link to="/manage/accounting/receivables">
|
||||
{t("menus.header.accounting-receivables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="payables">
|
||||
<Link to="/manage/accounting/payables">
|
||||
{t("menus.header.accounting-payables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="payments">
|
||||
<Link to="/manage/accounting/payments">
|
||||
{t("menus.header.accounting-payments")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
|
||||
<Menu.Item key="allpayments">
|
||||
<Link to="/manage/payments">
|
||||
{t("menus.header.allpayments")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu title={t("menus.header.shop")}>
|
||||
<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")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="shop-csi">
|
||||
<Link to="/manage/shop/csi">{t("menus.header.shop_csi")}</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.Item>
|
||||
<GlobalSearch />
|
||||
<Menu.Item key="payables">
|
||||
<Link to="/manage/accounting/payables">
|
||||
{t("menus.header.accounting-payables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu title={<ClockCircleFilled />}>
|
||||
{recentItems.map((i, idx) => (
|
||||
<Menu.Item key={idx}>
|
||||
<Link to={i.url}>{i.label}</Link>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
{currentUser.photoURL ? (
|
||||
<Avatar
|
||||
src={currentUser.photoURL}
|
||||
style={{
|
||||
margin: "10px",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Avatar
|
||||
style={{
|
||||
backgroundColor: "#87d068",
|
||||
margin: "10px",
|
||||
}}
|
||||
icon={<UserOutlined />}
|
||||
/>
|
||||
)}
|
||||
<Menu.Item key="payments">
|
||||
<Link to="/manage/accounting/payments">
|
||||
{t("menus.header.accounting-payments")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu title={t("menus.header.shop")}>
|
||||
<Menu.Item key="shop">
|
||||
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
|
||||
</Menu.Item>
|
||||
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item danger onClick={() => signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="shiftclock">
|
||||
<Link to="/manage/shiftclock">
|
||||
{t("menus.header.shiftclock")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile">
|
||||
{t("menus.currentuser.profile")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<GlobalOutlined />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en-US">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr-CA">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es-MX">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
</Col>
|
||||
</Row>
|
||||
<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")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="shop-csi">
|
||||
<Link to="/manage/shop/csi">{t("menus.header.shop_csi")}</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.Item>
|
||||
<GlobalSearch />
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu title={<ClockCircleFilled />}>
|
||||
{recentItems.map((i, idx) => (
|
||||
<Menu.Item key={idx}>
|
||||
<Link to={i.url}>{i.label}</Link>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
{currentUser.photoURL ? (
|
||||
<Avatar
|
||||
src={currentUser.photoURL}
|
||||
style={{
|
||||
margin: "10px",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Avatar
|
||||
style={{
|
||||
backgroundColor: "#87d068",
|
||||
margin: "10px",
|
||||
}}
|
||||
icon={<UserOutlined />}
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item danger onClick={() => signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="shiftclock">
|
||||
<Link to="/manage/shiftclock">{t("menus.header.shiftclock")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile">{t("menus.currentuser.profile")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<GlobalOutlined />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en-US">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr-CA">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es-MX">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
</Header>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,28 +5,41 @@ import { useTranslation } from "react-i18next";
|
||||
import { UPDATE_TEMPLATE } from "../../graphql/templates.queries";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
|
||||
export default function ShopTemplateSaveButton({ templateId, html, gql }) {
|
||||
export default function ShopTemplateSaveButton({
|
||||
templateId,
|
||||
gql,
|
||||
emailEditorRef,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updateTemplate] = useMutation(UPDATE_TEMPLATE);
|
||||
|
||||
const handleSave = async () => {
|
||||
logImEXEvent("shop_template_update");
|
||||
|
||||
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),
|
||||
}),
|
||||
emailEditorRef.current.exportHtml(async (data) => {
|
||||
console.log("handleSave -> html", data);
|
||||
const result = await updateTemplate({
|
||||
variables: {
|
||||
templateId: templateId,
|
||||
template: {
|
||||
query: gql,
|
||||
html: data.html,
|
||||
jsontemplate: data.design,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!!!result.errors) {
|
||||
notification["success"]({
|
||||
message: t("templates.successes.updated"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("templates.errors.updating", {
|
||||
error: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
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";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import EmailEditor from "react-email-editor";
|
||||
import ShopTemplateEditorSaveButton from "../shop-template-editor-save-button/shop-template-editor-save-button.component";
|
||||
|
||||
export default function ShopTemplateEditorComponent({
|
||||
templateId,
|
||||
html,
|
||||
gql,
|
||||
json,
|
||||
editorState,
|
||||
}) {
|
||||
const [editorContent, seteditorContent] = editorState;
|
||||
const emailEditorRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
seteditorContent((prevstate) => {
|
||||
return { ...prevstate, html: html };
|
||||
});
|
||||
}, [html, seteditorContent]);
|
||||
if (json && Object.keys(json).length > 0)
|
||||
emailEditorRef.current.loadDesign(json);
|
||||
}, [json, emailEditorRef]);
|
||||
|
||||
useEffect(() => {
|
||||
seteditorContent((prevstate) => {
|
||||
@@ -22,34 +24,29 @@ export default function ShopTemplateEditorComponent({
|
||||
});
|
||||
}, [gql, seteditorContent]);
|
||||
|
||||
const exportJson = (props) => {
|
||||
emailEditorRef.current.saveDesign((js) => {
|
||||
seteditorContent({ ...editorContent, JSON: js });
|
||||
console.log(js);
|
||||
});
|
||||
};
|
||||
|
||||
const exportHtml = (props) => {
|
||||
emailEditorRef.current.exportHtml((js) => {
|
||||
console.log(js);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ShopTemplateEditorSaveButton
|
||||
templateId={templateId}
|
||||
html={editorContent.html}
|
||||
gql={editorContent.gql}
|
||||
emailEditorRef={emailEditorRef}
|
||||
/>
|
||||
<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 })
|
||||
}
|
||||
/>
|
||||
<button onClick={exportJson}>json</button>
|
||||
<button onClick={exportHtml}>html</button>
|
||||
<EmailEditor ref={emailEditorRef} />
|
||||
QUERY
|
||||
<Input.TextArea
|
||||
value={editorContent.gql}
|
||||
|
||||
@@ -19,14 +19,14 @@ export default function ShopTemplateEditorContainer() {
|
||||
});
|
||||
|
||||
if (!!!search.customTemplateId) return <span>No selection.</span>;
|
||||
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
return (
|
||||
<LoadingSpinner loading={loading}>
|
||||
{data && data.templates_by_pk ? data.templates_by_pk.name : ""}
|
||||
<ShopTemplateEditorComponent
|
||||
templateId={search.customTemplateId}
|
||||
html={data && data.templates_by_pk ? data.templates_by_pk.html : ""}
|
||||
json={data && data.templates_by_pk && data.templates_by_pk.jsontemplate}
|
||||
gql={data && data.templates_by_pk ? data.templates_by_pk.query : ""}
|
||||
editorState={editorState}
|
||||
/>
|
||||
|
||||
@@ -4,9 +4,9 @@ export const QUERY_TEMPLATES_BY_NAME = gql`
|
||||
query QUERY_TEMPLATES_BY_NAME($name: String!) {
|
||||
templates(where: { name: { _eq: $name } }) {
|
||||
id
|
||||
html
|
||||
name
|
||||
query
|
||||
html
|
||||
bodyshopid
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ export const QUERY_TEMPLATE_BY_PK = gql`
|
||||
name
|
||||
query
|
||||
html
|
||||
jsontemplate
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -32,10 +32,10 @@ export function ShopTemplatesContainer({ setBreadcrumbs, bodyshop }) {
|
||||
return (
|
||||
<RbacWrapper action="shop:templates">
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<Col span={4}>
|
||||
<ShopTemplatesListContainer />
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Col span={20}>
|
||||
<div>
|
||||
<ShopTemplateEditor />
|
||||
</div>
|
||||
|
||||
@@ -938,8 +938,8 @@
|
||||
"invoices": "Invoices",
|
||||
"jobs": "Jobs",
|
||||
"owners": "Owners",
|
||||
"productionboard": "Production Board",
|
||||
"productionlist": "Production - List",
|
||||
"productionboard": "Production Board - Visual",
|
||||
"productionlist": "Production Board - List",
|
||||
"recent": "Recent Items",
|
||||
"schedule": "Schedule",
|
||||
"scoreboard": "Scoreboard",
|
||||
@@ -983,7 +983,7 @@
|
||||
"joblookup": "Job Lookup",
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
"productionboard": "Production Board",
|
||||
"productionboard": "Production Board - Visual",
|
||||
"productionlist": "Production List"
|
||||
}
|
||||
},
|
||||
@@ -1301,8 +1301,8 @@
|
||||
"owner-detail": "{{name}}",
|
||||
"owners": "Owners",
|
||||
"payments-all": "All Payments",
|
||||
"productionboard": "Production Board",
|
||||
"productionlist": "Production - List",
|
||||
"productionboard": "Production Board - Visual",
|
||||
"productionlist": "Production Board - List",
|
||||
"schedule": "Schedule",
|
||||
"scoreboard": "Scoreboard",
|
||||
"shop": "Manage my Shop ({{shopname}})",
|
||||
@@ -1332,7 +1332,7 @@
|
||||
"owners-detail": "{{name}} | $t(titles.app)",
|
||||
"payments-all": "Payments | $t(titles.app)",
|
||||
"productionboard": "Production - Board",
|
||||
"productionlist": "Production - List View | $t(titles.app)",
|
||||
"productionlist": "Production Board - List | $t(titles.app)",
|
||||
"profile": "My Profile | $t(titles.app)",
|
||||
"resetpassword": "Reset Password",
|
||||
"resetpasswordvalidate": "Enter New Password",
|
||||
|
||||
@@ -10876,6 +10876,11 @@ react-draggable@^4.0.0, react-draggable@^4.0.3:
|
||||
classnames "^2.2.5"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-email-editor@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-email-editor/-/react-email-editor-1.1.1.tgz#5a809c5588cf0a2042cf144771ef340cded36f92"
|
||||
integrity sha512-8V4Iba3dSw0eTmNQlmhisPv2EsiWAwEBVvKsWFiW/BcQ1x42vchbWCNCX7ss0njMQ9r7uReSptrcy10f4MtVEA==
|
||||
|
||||
react-error-overlay@^6.0.7:
|
||||
version "6.0.7"
|
||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: ALTER TABLE "public"."templates" DROP COLUMN "jsontemplate";
|
||||
type: run_sql
|
||||
@@ -0,0 +1,6 @@
|
||||
- args:
|
||||
cascade: false
|
||||
read_only: false
|
||||
sql: ALTER TABLE "public"."templates" ADD COLUMN "jsontemplate" jsonb NULL DEFAULT
|
||||
jsonb_build_object();
|
||||
type: run_sql
|
||||
@@ -0,0 +1,31 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_insert_permission
|
||||
- args:
|
||||
permission:
|
||||
check:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
columns:
|
||||
- bodyshopid
|
||||
- html
|
||||
- name
|
||||
- query
|
||||
set: {}
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_insert_permission
|
||||
@@ -0,0 +1,32 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_insert_permission
|
||||
- args:
|
||||
permission:
|
||||
check:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
columns:
|
||||
- bodyshopid
|
||||
- html
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
set: {}
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_insert_permission
|
||||
@@ -0,0 +1,35 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_select_permission
|
||||
- args:
|
||||
permission:
|
||||
allow_aggregations: false
|
||||
columns:
|
||||
- html
|
||||
- name
|
||||
- query
|
||||
- created_at
|
||||
- updated_at
|
||||
- bodyshopid
|
||||
- id
|
||||
computed_fields: []
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_select_permission
|
||||
@@ -0,0 +1,36 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_select_permission
|
||||
- args:
|
||||
permission:
|
||||
allow_aggregations: false
|
||||
columns:
|
||||
- bodyshopid
|
||||
- created_at
|
||||
- html
|
||||
- id
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
- updated_at
|
||||
computed_fields: []
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_select_permission
|
||||
@@ -0,0 +1,34 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_update_permission
|
||||
- args:
|
||||
permission:
|
||||
columns:
|
||||
- html
|
||||
- name
|
||||
- query
|
||||
- created_at
|
||||
- updated_at
|
||||
- bodyshopid
|
||||
- id
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
set: {}
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_update_permission
|
||||
@@ -0,0 +1,35 @@
|
||||
- args:
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: drop_update_permission
|
||||
- args:
|
||||
permission:
|
||||
columns:
|
||||
- bodyshopid
|
||||
- created_at
|
||||
- html
|
||||
- id
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
- updated_at
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
_is_null: true
|
||||
- bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
set: {}
|
||||
role: user
|
||||
table:
|
||||
name: templates
|
||||
schema: public
|
||||
type: create_update_permission
|
||||
@@ -3569,19 +3569,21 @@ tables:
|
||||
columns:
|
||||
- bodyshopid
|
||||
- html
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
select_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- bodyshopid
|
||||
- created_at
|
||||
- html
|
||||
- id
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
- created_at
|
||||
- updated_at
|
||||
- bodyshopid
|
||||
- id
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
@@ -3598,13 +3600,14 @@ tables:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- bodyshopid
|
||||
- created_at
|
||||
- html
|
||||
- id
|
||||
- jsontemplate
|
||||
- name
|
||||
- query
|
||||
- created_at
|
||||
- updated_at
|
||||
- bodyshopid
|
||||
- id
|
||||
filter:
|
||||
_or:
|
||||
- bodyshopid:
|
||||
|
||||
Reference in New Issue
Block a user