Skip to content

Commit ac5105a

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents a9bc4bd + ccc1408 commit ac5105a

File tree

33 files changed

+926
-191
lines changed

33 files changed

+926
-191
lines changed

cms-live-preview/5.40.x/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ To enable these extensions in your existing Webiny project, follow these steps:
1313
In your project, run:
1414

1515
```shell
16-
yarn webiny scaffold extension cms-live-preview
16+
yarn webiny extension cms-live-preview
1717
```
1818

1919
### 2. Configure the `website` app
@@ -30,14 +30,15 @@ Add component styles to the `website` app, in `apps/website/public/index.html`:
3030

3131
Add live preview route in `apps/website/src/App.tsx`:
3232

33-
```tsx
33+
```diff tsx
3434
import React from "react";
3535
import { Website } from "@webiny/app-website";
36-
import { createLivePreviewRoute } from "@demo/live-preview-website";
36+
+ import { createLivePreviewRoute } from "@demo/website";
3737
import "./App.scss";
3838

3939
export const App = () => {
40-
return <Website routes={[createLivePreviewRoute()]} />;
40+
- return <Website/>;
41+
+ return <Website routes={[createLivePreviewRoute()]} />;
4142
};
4243
```
4344

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "custom-cms-entry-form-layout",
3+
"main": "src/index.tsx",
4+
"version": "1.0.0",
5+
"keywords": [
6+
"webiny-extension",
7+
"webiny-extension-type:admin"
8+
],
9+
"dependencies": {
10+
"@webiny/app-headless-cms": "0.0.0",
11+
"@webiny/app-serverless-cms": "0.0.0",
12+
"@webiny/ui": "0.0.0",
13+
"react": "18.2.0"
14+
}
15+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from "react";
2+
import { useSecurity } from "@webiny/app-serverless-cms";
3+
import { CmsContentFormRendererPlugin } from "@webiny/app-headless-cms";
4+
import { Grid, Cell } from "@webiny/ui/Grid";
5+
import { Tabs, Tab } from "@webiny/ui/Tabs";
6+
import { Alert } from "@webiny/ui/Alert";
7+
8+
type CmsContentFormRendererProps = React.ComponentProps<typeof CmsContentFormRendererPlugin>;
9+
10+
const PizzaLayout: CmsContentFormRendererProps["render"] = ({ fields, data }) => {
11+
// Access security identity.
12+
const { getPermission } = useSecurity();
13+
14+
// Get the necessary permission.
15+
const bakeryPermission = getPermission("bakery");
16+
17+
// Check if the user has the permission to edit a recipe.
18+
const canEditRecipe = bakeryPermission && bakeryPermission["canEditRecipe"] === true;
19+
20+
const priceTooLow = data["price"] < 20 && data["numberOfIngredients"] > 6;
21+
22+
return (
23+
<Tabs>
24+
<Tab label="General">
25+
{priceTooLow && (
26+
<Grid>
27+
<Cell span={12}>
28+
<Alert type={"warning"} title={"Please double-check your input"}>
29+
The price of <strong>{data["price"]}</strong> seems too low for a
30+
pizza with over <strong>6</strong> ingredients.
31+
</Alert>
32+
</Cell>
33+
</Grid>
34+
)}
35+
36+
<Grid>
37+
<Cell span={12}>{fields["name"]}</Cell>
38+
</Grid>
39+
<Grid>
40+
<Cell span={6}>{fields["price"]}</Cell>
41+
<Cell span={6}>{fields["numberOfIngredients"]}</Cell>
42+
</Grid>
43+
</Tab>
44+
{/* Hide the Recipe tab if the user doesn't have the required permission. */}
45+
{canEditRecipe && (
46+
<Tab label="Recipe">
47+
<Grid>
48+
<Cell span={12}>{fields["recipe"]}</Cell>
49+
</Grid>
50+
</Tab>
51+
)}
52+
<Tab label="History">
53+
<Grid>
54+
<Cell span={12}>{fields["history"]}</Cell>
55+
</Grid>
56+
</Tab>
57+
</Tabs>
58+
);
59+
};
60+
61+
export const Extension = () => {
62+
return (
63+
<>
64+
<CmsContentFormRendererPlugin modelId="pizza" render={PizzaLayout} />
65+
</>
66+
);
67+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "models",
3+
"main": "src/index.ts",
4+
"keywords": [
5+
"webiny-extension",
6+
"webiny-extension-type:api"
7+
],
8+
"version": "1.0.0",
9+
"dependencies": {
10+
"@webiny/api-headless-cms": "0.0.0"
11+
}
12+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import {
2+
createCmsGroupPlugin,
3+
createCmsModelPlugin,
4+
createModelField
5+
} from "@webiny/api-headless-cms";
6+
7+
export const createExtension = () => {
8+
return [
9+
// Defines a new "E-Commerce" content models group.
10+
createCmsGroupPlugin({
11+
id: "pizzeria",
12+
name: "Pizzeria",
13+
description: "Pizzeria-related content models.",
14+
slug: "pizzeria",
15+
icon: "fas/pizza-slice"
16+
}),
17+
18+
// Defines a new "Product" content model.
19+
createCmsModelPlugin({
20+
name: "Pizza",
21+
modelId: "pizza",
22+
description: "Pizza related content.",
23+
group: {
24+
id: "pizzeria",
25+
name: "Pizzeria"
26+
},
27+
fields: [
28+
createModelField({
29+
id: "gaj2w2eb",
30+
fieldId: "name",
31+
storageId: "text@gaj2w2eb",
32+
type: "text",
33+
label: "Name",
34+
renderer: {
35+
name: "text-input",
36+
settings: {}
37+
},
38+
validation: [
39+
{
40+
name: "required",
41+
settings: {},
42+
message: "Title is a required field."
43+
}
44+
]
45+
}),
46+
createModelField({
47+
id: "wz3runy7",
48+
fieldId: "price",
49+
storageId: "number@wz3runy7",
50+
type: "number",
51+
label: "Price",
52+
renderer: {
53+
name: "number-input",
54+
settings: {}
55+
}
56+
}),
57+
createModelField({
58+
id: "s7wqd2g0",
59+
fieldId: "numberOfIngredients",
60+
storageId: "number@s7wqd2g0",
61+
type: "number",
62+
label: "Number of ingredients",
63+
renderer: {
64+
name: "number-input",
65+
settings: {}
66+
}
67+
}),
68+
createModelField({
69+
id: "pcofsq5m",
70+
fieldId: "glutenFree",
71+
storageId: "boolean@pcofsq5m",
72+
type: "boolean",
73+
label: "Gluten-free",
74+
renderer: {
75+
name: "boolean-input",
76+
settings: {}
77+
},
78+
settings: {
79+
defaultValue: false
80+
}
81+
}),
82+
createModelField({
83+
id: "02hbjdy6",
84+
fieldId: "recipe",
85+
storageId: "long-text@02hbjdy6",
86+
type: "long-text",
87+
label: "Recipe",
88+
renderer: {
89+
name: "long-text-text-area",
90+
settings: {}
91+
}
92+
}),
93+
createModelField({
94+
id: "occavfqi",
95+
fieldId: "history",
96+
storageId: "long-text@occavfqi",
97+
type: "long-text",
98+
label: "History",
99+
renderer: {
100+
name: "long-text-text-area",
101+
settings: {}
102+
}
103+
})
104+
],
105+
icon: "fas/pizza-slice",
106+
descriptionFieldId: "recipe",
107+
layout: [
108+
["gaj2w2eb"],
109+
["wz3runy7"],
110+
["s7wqd2g0"],
111+
["pcofsq5m"],
112+
["02hbjdy6"],
113+
["occavfqi"]
114+
],
115+
titleFieldId: "name"
116+
})
117+
];
118+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"include": ["src"]
4+
}

custom-cms-entry-form-layout/extensions/customCmsEntryFormLayout/package.json

Lines changed: 0 additions & 14 deletions
This file was deleted.

custom-cms-entry-form-layout/extensions/customCmsEntryFormLayout/src/index.tsx

Lines changed: 0 additions & 57 deletions
This file was deleted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React, { useEffect } from "react";
2+
import { plugins } from "@webiny/plugins";
3+
import type { CmsContentFormRendererPlugin } from "@webiny/app-headless-cms/types";
4+
import { Alert } from '@webiny/ui/Alert'
5+
import { Grid, Cell } from "@webiny/ui/Grid";
6+
import { Tabs, Tab } from "@webiny/ui/Tabs";
7+
8+
interface LayoutProps {
9+
fields: Record<string, JSX.Element>;
10+
data: Record<string, any>
11+
}
12+
13+
const PizzaLayout = ({ fields, data }: LayoutProps) => {
14+
const priceTooLow = data['price'] < 20 && data['numberOfIngredients'] > 6
15+
16+
return (
17+
<Tabs>
18+
19+
<Tab label="General">
20+
{priceTooLow && (
21+
<Grid>
22+
<Cell span={12}>
23+
<Alert type={'warning'} title={'Please double-check your input'}>
24+
The price of <strong>{data['price']}</strong> seems too low for a pizza with over{' '}
25+
<strong>6</strong> ingredients.
26+
</Alert>
27+
</Cell>
28+
</Grid>
29+
)}
30+
<Grid>
31+
<Cell span={12}>{fields['name']}</Cell>
32+
</Grid>
33+
<Grid>
34+
<Cell span={6}>{fields['price']}</Cell>
35+
<Cell span={6}>{fields['numberOfIngredients']}</Cell>
36+
</Grid>
37+
</Tab>
38+
39+
<Tab label="Recipe">
40+
<Grid>
41+
<Cell span={12}>{fields['recipe']}</Cell>
42+
</Grid>
43+
</Tab>
44+
45+
<Tab label="History">
46+
<Grid>
47+
<Cell span={12}>{fields['history']}</Cell>
48+
</Grid>
49+
</Tab>
50+
</Tabs>
51+
);
52+
};
53+
54+
export const Extension = () => {
55+
useEffect(() => {
56+
const layoutPlugin: CmsContentFormRendererPlugin = {
57+
type: "cms-content-form-renderer",
58+
modelId: "pizza",
59+
render(props) {
60+
return <PizzaLayout {...props} />;
61+
},
62+
};
63+
64+
plugins.register(layoutPlugin);
65+
}, []);
66+
67+
return null;
68+
};

0 commit comments

Comments
 (0)