Added new HTML editor with some breaking changes.

This commit is contained in:
Patrick Fic
2020-08-14 15:50:36 -07:00
parent 57cbc6961c
commit 873e81556d
20 changed files with 574 additions and 358 deletions

View File

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

View 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",

View File

@@ -45,7 +45,7 @@ export default function FormsFieldChanged({ form }) {
/>
</div>
);
return null;
return <div style={{ display: "none" }}></div>;
}}
</Form.Item>
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."templates" DROP COLUMN "jsontemplate";
type: run_sql

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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