slice-machine-ui 1.11.1-dev-next-release.4 → 1.11.1-dev-slice-tenplate-feature-2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ModalFormCard/index.tsx +102 -93
- package/lib/builders/CustomTypeBuilder/SliceZone/SlicesTemplatesModal.tsx +88 -0
- package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModal.tsx +2 -3
- package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModalList.tsx +36 -6
- package/lib/builders/CustomTypeBuilder/SliceZone/index.tsx +92 -12
- package/lib/builders/CustomTypeBuilder/SliceZone/sliceTemplatesComingSoon.ts +122 -0
- package/lib/builders/CustomTypeBuilder/TabZone/index.tsx +50 -39
- package/lib/builders/common/Zone/components/EmptyState/index.tsx +13 -14
- package/lib/builders/common/Zone/index.jsx +22 -33
- package/out/404.html +1 -1
- package/out/[lib]/[sliceName]/[variation]/screenshot.html +1 -1
- package/out/[lib]/[sliceName]/[variation]/simulator.html +1 -1
- package/out/[lib]/[sliceName]/[variation].html +1 -1
- package/out/_next/static/a84hXu0hKKBqhkOgLrr1K/_buildManifest.js +1 -0
- package/out/_next/static/chunks/18539003-b49b17dc02a89c7b.js +101 -0
- package/out/_next/static/chunks/377-04a57b21fc2cae35.js +1 -0
- package/out/_next/static/chunks/{482-ad5ef8eecedd8b52.js → 482-5ae2d1fd2572cb1f.js} +1 -1
- package/out/_next/static/chunks/{573-aaae870d20e5f86c.js → 573-c4f805b20b6710f3.js} +1 -1
- package/out/_next/static/chunks/777-b833ba5749997505.js +1 -0
- package/out/_next/static/chunks/{740-d0642219804fa9f0.js → 791-091202c1718b4ac3.js} +2 -2
- package/out/_next/static/chunks/799-48a1855b96a3623f.js +1 -0
- package/out/_next/static/chunks/962-6beea758652e94f7.js +1 -0
- package/out/_next/static/chunks/pages/[lib]/[sliceName]/[variation]/{simulator-2c6033d99c3672e0.js → simulator-e51d1161076d4797.js} +1 -1
- package/out/_next/static/chunks/pages/[lib]/[sliceName]/{[variation]-bd1822e54ac8836c.js → [variation]-4b4fed1e884838ad.js} +1 -1
- package/out/_next/static/chunks/pages/{_app-2351f4803a15a482.js → _app-441ee3050f578732.js} +98 -98
- package/out/_next/static/chunks/pages/{changelog-dda7774c702c6b47.js → changelog-c08cc37b54d73a60.js} +1 -1
- package/out/_next/static/chunks/pages/{changes-26dab4f4657a54e4.js → changes-3b7c6b9b312b5e2f.js} +1 -1
- package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-a69df1ad7fd8b927.js → [customTypeId]-207b0c837912e5a9.js} +1 -1
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-5e4e26de800fccff.js → [pageTypeId]-a6a8ebd9f4b3b608.js} +1 -1
- package/out/_next/static/chunks/pages/slices-24d2714462334469.js +1 -0
- package/out/_next/static/css/{6639e1548a7d3442.css → a978ac70ea31c6d7.css} +1 -1
- package/out/_next/static/css/{6c430d5aaa4ef12a.css → bbe0f7491bdca3fc.css} +1 -1
- package/out/_next/static/css/de841cf04740a2ad.css +1 -0
- package/out/_next/static/css/{d4b59834999106a5.css → f7381722c36382c6.css} +1 -1
- package/out/alternateGrid.png +0 -0
- package/out/changelog.html +1 -1
- package/out/changes.html +1 -1
- package/out/custom-types/[customTypeId].html +1 -1
- package/out/custom-types.html +1 -1
- package/out/customerLogos.png +0 -0
- package/out/hero.png +0 -0
- package/out/index.html +1 -1
- package/out/page-types/[pageTypeId].html +1 -1
- package/out/slices.html +1 -1
- package/out/videoHighlight.png +0 -0
- package/package.json +7 -7
- package/public/alternateGrid.png +0 -0
- package/public/customerLogos.png +0 -0
- package/public/hero.png +0 -0
- package/public/videoHighlight.png +0 -0
- package/src/components/List/List.css.ts +0 -2
- package/src/components/List/List.tsx +3 -7
- package/src/features/customTypes/customTypesBuilder/SliceZoneBlankSlate.tsx +16 -4
- package/src/features/customTypes/customTypesMessages.ts +2 -2
- package/src/features/slicesTemplates/actions/createSlicesTemplates.ts +41 -0
- package/src/features/slicesTemplates/useSlicesTemplates.ts +37 -0
- package/test/pages/custom-types.test.tsx +38 -20
- package/out/_next/static/N2nU1yPW38KWsgo9OL-hs/_buildManifest.js +0 -1
- package/out/_next/static/chunks/119-626b7b48e4535694.js +0 -1
- package/out/_next/static/chunks/18539003-b0b0df3d19f7d641.js +0 -101
- package/out/_next/static/chunks/377-c283ea91a489e394.js +0 -1
- package/out/_next/static/chunks/677-d8555c165c261511.js +0 -1
- package/out/_next/static/chunks/799-4787c871f6119407.js +0 -1
- package/out/_next/static/chunks/pages/slices-d1c96629e458440c.js +0 -1
- package/out/_next/static/css/74653a9f89a68929.css +0 -1
- /package/out/_next/static/{N2nU1yPW38KWsgo9OL-hs → a84hXu0hKKBqhkOgLrr1K}/_ssgManifest.js +0 -0
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
FormikErrors,
|
|
7
7
|
FormikTouched,
|
|
8
8
|
FormikValues,
|
|
9
|
+
FormikProps,
|
|
9
10
|
} from "formik";
|
|
10
|
-
import {
|
|
11
|
+
import { SetStateAction } from "react";
|
|
11
12
|
import { Flex, Heading, Close, Button as ThemeButton } from "theme-ui";
|
|
12
13
|
|
|
13
14
|
import { Button } from "@components/Button";
|
|
@@ -44,7 +45,9 @@ type ModalCardProps<T extends FormikValues> = {
|
|
|
44
45
|
omitFooter?: boolean;
|
|
45
46
|
isLoading?: boolean;
|
|
46
47
|
dataCy?: string;
|
|
47
|
-
actionMessage?:
|
|
48
|
+
actionMessage?:
|
|
49
|
+
| ((props: FormikProps<T>) => React.ReactNode)
|
|
50
|
+
| React.ReactNode;
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
function ModalCard<Values extends FormikValues>({
|
|
@@ -88,102 +91,108 @@ function ModalCard<Values extends FormikValues>({
|
|
|
88
91
|
onSubmit(values);
|
|
89
92
|
}}
|
|
90
93
|
>
|
|
91
|
-
{({
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
top: 0,
|
|
120
|
-
zIndex: 1,
|
|
121
|
-
p: "16px",
|
|
122
|
-
pl: 4,
|
|
123
|
-
bg: "headSection",
|
|
124
|
-
alignItems: "center",
|
|
125
|
-
justifyContent: "space-between",
|
|
126
|
-
borderTopLeftRadius: radius,
|
|
127
|
-
borderTopRightRadius: radius,
|
|
128
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
129
|
-
borderBottom: (t) => `1px solid ${t.colors?.borders}`,
|
|
130
|
-
}}
|
|
131
|
-
>
|
|
132
|
-
<Heading sx={{ fontSize: "20px" }}>{title}</Heading>
|
|
133
|
-
<Close type="button" onClick={close} />
|
|
134
|
-
</Flex>
|
|
135
|
-
)}
|
|
136
|
-
Footer={
|
|
137
|
-
!omitFooter ? (
|
|
94
|
+
{(formikProps) => {
|
|
95
|
+
const {
|
|
96
|
+
isValid,
|
|
97
|
+
isSubmitting,
|
|
98
|
+
values,
|
|
99
|
+
errors,
|
|
100
|
+
touched,
|
|
101
|
+
setFieldValue,
|
|
102
|
+
setValues,
|
|
103
|
+
} = formikProps;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<Form
|
|
107
|
+
id={formId}
|
|
108
|
+
{...(dataCy != null ? { "data-cy": dataCy } : null)}
|
|
109
|
+
>
|
|
110
|
+
<Card
|
|
111
|
+
borderFooter
|
|
112
|
+
footerSx={{
|
|
113
|
+
p: 3,
|
|
114
|
+
position: "sticky",
|
|
115
|
+
bottom: 0,
|
|
116
|
+
background: "gray",
|
|
117
|
+
}}
|
|
118
|
+
bodySx={{ px: 4, py: 4 }}
|
|
119
|
+
sx={{ border: "none" }}
|
|
120
|
+
{...cardProps}
|
|
121
|
+
Header={({ radius }: { radius: string | number }) => (
|
|
138
122
|
<Flex
|
|
139
123
|
sx={{
|
|
140
|
-
|
|
124
|
+
position: "sticky",
|
|
125
|
+
top: 0,
|
|
126
|
+
zIndex: 1,
|
|
127
|
+
p: "16px",
|
|
128
|
+
pl: 4,
|
|
129
|
+
bg: "headSection",
|
|
130
|
+
alignItems: "center",
|
|
131
|
+
justifyContent: "space-between",
|
|
132
|
+
borderTopLeftRadius: radius,
|
|
133
|
+
borderTopRightRadius: radius,
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
135
|
+
borderBottom: (t) => `1px solid ${t.colors?.borders}`,
|
|
141
136
|
}}
|
|
142
137
|
>
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
</Flex>
|
|
146
|
-
<Flex sx={{ ml: "auto" }}>
|
|
147
|
-
<ThemeButton
|
|
148
|
-
mr={2}
|
|
149
|
-
type="button"
|
|
150
|
-
onClick={close}
|
|
151
|
-
variant="secondary"
|
|
152
|
-
disabled={isSubmitting || isLoading}
|
|
153
|
-
>
|
|
154
|
-
Cancel
|
|
155
|
-
</ThemeButton>
|
|
156
|
-
<Button
|
|
157
|
-
label={buttonLabel}
|
|
158
|
-
form={formId}
|
|
159
|
-
type="submit"
|
|
160
|
-
disabled={!isValid || isSubmitting || isLoading}
|
|
161
|
-
isLoading={isSubmitting || isLoading}
|
|
162
|
-
sx={{
|
|
163
|
-
fontWeight: "400",
|
|
164
|
-
paddingBlock: "8px",
|
|
165
|
-
paddingInline: "16px",
|
|
166
|
-
fontSize: "14px",
|
|
167
|
-
borderRadius: "4px",
|
|
168
|
-
}}
|
|
169
|
-
/>
|
|
170
|
-
</Flex>
|
|
138
|
+
<Heading sx={{ fontSize: "20px" }}>{title}</Heading>
|
|
139
|
+
<Close type="button" onClick={close} />
|
|
171
140
|
</Flex>
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
141
|
+
)}
|
|
142
|
+
Footer={
|
|
143
|
+
!omitFooter ? (
|
|
144
|
+
<Flex
|
|
145
|
+
sx={{
|
|
146
|
+
alignItems: "space-between",
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<Flex sx={{ fontSize: "14px", alignItems: "center" }}>
|
|
150
|
+
{typeof actionMessage === "function"
|
|
151
|
+
? actionMessage(formikProps)
|
|
152
|
+
: actionMessage}
|
|
153
|
+
</Flex>
|
|
154
|
+
<Flex sx={{ ml: "auto" }}>
|
|
155
|
+
<ThemeButton
|
|
156
|
+
mr={2}
|
|
157
|
+
type="button"
|
|
158
|
+
onClick={close}
|
|
159
|
+
variant="secondary"
|
|
160
|
+
disabled={isSubmitting || isLoading}
|
|
161
|
+
>
|
|
162
|
+
Cancel
|
|
163
|
+
</ThemeButton>
|
|
164
|
+
<Button
|
|
165
|
+
label={buttonLabel}
|
|
166
|
+
form={formId}
|
|
167
|
+
type="submit"
|
|
168
|
+
disabled={!isValid || isSubmitting || isLoading}
|
|
169
|
+
isLoading={isSubmitting || isLoading}
|
|
170
|
+
sx={{
|
|
171
|
+
fontWeight: "400",
|
|
172
|
+
paddingBlock: "8px",
|
|
173
|
+
paddingInline: "16px",
|
|
174
|
+
fontSize: "14px",
|
|
175
|
+
borderRadius: "4px",
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</Flex>
|
|
179
|
+
</Flex>
|
|
180
|
+
) : null
|
|
181
|
+
}
|
|
182
|
+
>
|
|
183
|
+
{children({
|
|
184
|
+
isValid,
|
|
185
|
+
isSubmitting,
|
|
186
|
+
values,
|
|
187
|
+
errors,
|
|
188
|
+
touched,
|
|
189
|
+
setFieldValue,
|
|
190
|
+
setValues,
|
|
191
|
+
})}
|
|
192
|
+
</Card>
|
|
193
|
+
</Form>
|
|
194
|
+
);
|
|
195
|
+
}}
|
|
187
196
|
</Formik>
|
|
188
197
|
</SliceMachineModal>
|
|
189
198
|
);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { Text } from "theme-ui";
|
|
3
|
+
|
|
4
|
+
import { SliceTemplate } from "@src/features/slicesTemplates/useSlicesTemplates";
|
|
5
|
+
import { Slices } from "@lib/models/common/Slice";
|
|
6
|
+
import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
7
|
+
import UpdateSliceZoneModalList from "./UpdateSliceZoneModalList";
|
|
8
|
+
import ModalFormCard from "../../../../components/ModalFormCard";
|
|
9
|
+
import { sliceTemplatesComingSoon } from "./sliceTemplatesComingSoon";
|
|
10
|
+
|
|
11
|
+
interface UpdateSliceModalProps {
|
|
12
|
+
isOpen: boolean;
|
|
13
|
+
formId: string;
|
|
14
|
+
close: () => void;
|
|
15
|
+
onSubmit: (values: SliceZoneFormValues) => void;
|
|
16
|
+
availableSlicesTemplates: SliceTemplate[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type SliceZoneFormValues = {
|
|
20
|
+
sliceKeys: string[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const SlicesTemplatesModal: FC<UpdateSliceModalProps> = ({
|
|
24
|
+
isOpen,
|
|
25
|
+
formId,
|
|
26
|
+
close,
|
|
27
|
+
onSubmit,
|
|
28
|
+
availableSlicesTemplates,
|
|
29
|
+
}) => {
|
|
30
|
+
return (
|
|
31
|
+
<ModalFormCard
|
|
32
|
+
buttonLabel="Create"
|
|
33
|
+
isOpen={isOpen}
|
|
34
|
+
formId={formId}
|
|
35
|
+
close={close}
|
|
36
|
+
onSubmit={(values: SliceZoneFormValues) => {
|
|
37
|
+
onSubmit(values);
|
|
38
|
+
}}
|
|
39
|
+
initialValues={{
|
|
40
|
+
sliceKeys: [],
|
|
41
|
+
}}
|
|
42
|
+
content={{
|
|
43
|
+
title: "Create slices from template",
|
|
44
|
+
}}
|
|
45
|
+
validate={(values) => {
|
|
46
|
+
if (values.sliceKeys.length === 0) {
|
|
47
|
+
return {
|
|
48
|
+
sliceKeys: "Please select at least one slice template",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}}
|
|
52
|
+
actionMessage={({ errors }) =>
|
|
53
|
+
errors.sliceKeys !== undefined ? (
|
|
54
|
+
<Text sx={{ color: "error" }}>{errors.sliceKeys}</Text>
|
|
55
|
+
) : undefined
|
|
56
|
+
}
|
|
57
|
+
>
|
|
58
|
+
{({ values }) => (
|
|
59
|
+
<UpdateSliceZoneModalList
|
|
60
|
+
values={values}
|
|
61
|
+
placeholderSlices={sliceTemplatesComingSoon}
|
|
62
|
+
availableSlices={[
|
|
63
|
+
...availableSlicesTemplates.map(
|
|
64
|
+
(slice): ComponentUI => ({
|
|
65
|
+
extension: "",
|
|
66
|
+
fileName: "",
|
|
67
|
+
from: "",
|
|
68
|
+
href: "",
|
|
69
|
+
pathToSlice: "",
|
|
70
|
+
model: Slices.toSM(slice.model),
|
|
71
|
+
screenshots: Object.entries(slice.screenshots).reduce(
|
|
72
|
+
(acc, curr) => ({
|
|
73
|
+
...acc,
|
|
74
|
+
[curr[0]]: {
|
|
75
|
+
url: curr[1],
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
{}
|
|
79
|
+
),
|
|
80
|
+
})
|
|
81
|
+
),
|
|
82
|
+
...sliceTemplatesComingSoon,
|
|
83
|
+
]}
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
</ModalFormCard>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
1
2
|
import ModalFormCard from "../../../../components/ModalFormCard";
|
|
2
|
-
|
|
3
3
|
import UpdateSliceZoneModalList from "./UpdateSliceZoneModalList";
|
|
4
|
-
import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
5
4
|
|
|
6
5
|
interface UpdateSliceModalProps {
|
|
7
6
|
isOpen: boolean;
|
|
@@ -38,7 +37,7 @@ const UpdateSliceZoneModal: React.FC<UpdateSliceModalProps> = ({
|
|
|
38
37
|
sliceKeys: slicesInSliceZone.map((slice) => slice.model.id),
|
|
39
38
|
}}
|
|
40
39
|
content={{
|
|
41
|
-
title: "Update
|
|
40
|
+
title: "Update slices",
|
|
42
41
|
}}
|
|
43
42
|
dataCy="update-slices-modal"
|
|
44
43
|
>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FieldArray } from "formik";
|
|
2
|
-
import { Checkbox, Box } from "theme-ui";
|
|
2
|
+
import { Checkbox, Box, Text } from "theme-ui";
|
|
3
3
|
|
|
4
4
|
import { SharedSlice } from "@lib/models/ui/Slice";
|
|
5
5
|
|
|
@@ -10,7 +10,8 @@ import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
|
10
10
|
const UpdateSliceZoneModalList: React.FC<{
|
|
11
11
|
availableSlices: ReadonlyArray<ComponentUI>;
|
|
12
12
|
values: SliceZoneFormValues;
|
|
13
|
-
|
|
13
|
+
placeholderSlices?: ReadonlyArray<ComponentUI>;
|
|
14
|
+
}> = ({ availableSlices, values, placeholderSlices }) => (
|
|
14
15
|
<FieldArray
|
|
15
16
|
name="sliceKeys"
|
|
16
17
|
render={(arrayHelpers) => (
|
|
@@ -19,6 +20,10 @@ const UpdateSliceZoneModalList: React.FC<{
|
|
|
19
20
|
elems={availableSlices}
|
|
20
21
|
defineElementKey={(slice: ComponentUI) => slice.model.name}
|
|
21
22
|
renderElem={(slice: ComponentUI) => {
|
|
23
|
+
const isPlaceholderSlice = placeholderSlices?.find(
|
|
24
|
+
(s) => s.model.id === slice.model.id
|
|
25
|
+
);
|
|
26
|
+
|
|
22
27
|
return SharedSlice.render({
|
|
23
28
|
slice: slice,
|
|
24
29
|
Wrapper: ({ slice, children, sx }) => {
|
|
@@ -26,6 +31,10 @@ const UpdateSliceZoneModalList: React.FC<{
|
|
|
26
31
|
<Box
|
|
27
32
|
data-testid="slicezone-modal-item"
|
|
28
33
|
onClick={() => {
|
|
34
|
+
if (isPlaceholderSlice) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
const isInSliceZone = values.sliceKeys.includes(
|
|
30
39
|
slice.model.id
|
|
31
40
|
);
|
|
@@ -37,16 +46,37 @@ const UpdateSliceZoneModalList: React.FC<{
|
|
|
37
46
|
arrayHelpers.push(slice.model.id);
|
|
38
47
|
}}
|
|
39
48
|
key={`${slice.from}-${slice.model.name}`}
|
|
40
|
-
sx={
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
sx={
|
|
50
|
+
!isPlaceholderSlice
|
|
51
|
+
? {
|
|
52
|
+
cursor: "pointer",
|
|
53
|
+
...sx,
|
|
54
|
+
}
|
|
55
|
+
: {
|
|
56
|
+
opacity: 0.5,
|
|
57
|
+
...sx,
|
|
58
|
+
}
|
|
59
|
+
}
|
|
44
60
|
>
|
|
45
61
|
{children}
|
|
46
62
|
</Box>
|
|
47
63
|
);
|
|
48
64
|
},
|
|
49
65
|
StatusOrCustom: ({ slice }: { slice: ComponentUI }) => {
|
|
66
|
+
if (isPlaceholderSlice) {
|
|
67
|
+
return (
|
|
68
|
+
<Text
|
|
69
|
+
sx={{
|
|
70
|
+
fontSize: 12,
|
|
71
|
+
color: "purpleStrong",
|
|
72
|
+
fontWeight: "bold",
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
Coming soon
|
|
76
|
+
</Text>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
50
80
|
const isInSliceZone = values.sliceKeys.includes(slice.model.id);
|
|
51
81
|
|
|
52
82
|
return (
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Box,
|
|
4
|
+
Switch,
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuTrigger,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuItem,
|
|
9
|
+
Icon,
|
|
10
|
+
} from "@prismicio/editor-ui";
|
|
2
11
|
import { useEffect, useMemo, useState } from "react";
|
|
3
12
|
import { useSelector } from "react-redux";
|
|
4
13
|
import { BaseStyles } from "theme-ui";
|
|
@@ -21,10 +30,15 @@ import {
|
|
|
21
30
|
getRemoteSlices,
|
|
22
31
|
} from "@src/modules/slices";
|
|
23
32
|
import type { SliceMachineStoreType } from "@src/redux/type";
|
|
33
|
+
import { useSlicesTemplates } from "@src/features/slicesTemplates/useSlicesTemplates";
|
|
34
|
+
import { createSlicesTemplates } from "@src/features/slicesTemplates/actions/createSlicesTemplates";
|
|
24
35
|
|
|
25
36
|
import { DeleteSliceZoneModal } from "./DeleteSliceZoneModal";
|
|
26
37
|
import { SlicesList } from "./List";
|
|
27
38
|
import UpdateSliceZoneModal from "./UpdateSliceZoneModal";
|
|
39
|
+
import { SlicesTemplatesModal } from "./SlicesTemplatesModal";
|
|
40
|
+
import { getState } from "@src/apiClient";
|
|
41
|
+
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
28
42
|
|
|
29
43
|
const mapAvailableAndSharedSlices = (
|
|
30
44
|
sliceZone: SlicesSM,
|
|
@@ -100,7 +114,11 @@ const SliceZone: React.FC<SliceZoneProps> = ({
|
|
|
100
114
|
sliceZone,
|
|
101
115
|
tabId,
|
|
102
116
|
}) => {
|
|
103
|
-
const
|
|
117
|
+
const availableSlicesTemplates = useSlicesTemplates();
|
|
118
|
+
const [isSlicesTemplatesModalOpen, setIsSlicesTemplatesModalOpen] =
|
|
119
|
+
useState(false);
|
|
120
|
+
const [isUpdateSliceZoneModalOpen, setIsUpdateSliceZoneModalOpen] =
|
|
121
|
+
useState(false);
|
|
104
122
|
const [isCreateSliceModalOpen, setIsCreateSliceModalOpen] = useState(false);
|
|
105
123
|
const { remoteSlices, libraries, slices } = useSelector(
|
|
106
124
|
(store: SliceMachineStoreType) => ({
|
|
@@ -109,6 +127,7 @@ const SliceZone: React.FC<SliceZoneProps> = ({
|
|
|
109
127
|
slices: getFrontendSlices(store),
|
|
110
128
|
})
|
|
111
129
|
);
|
|
130
|
+
const { createSliceSuccess } = useSliceMachineActions();
|
|
112
131
|
const localLibraries: readonly LibraryUI[] = libraries.filter(
|
|
113
132
|
(library) => library.isLocal
|
|
114
133
|
);
|
|
@@ -142,33 +161,63 @@ const SliceZone: React.FC<SliceZoneProps> = ({
|
|
|
142
161
|
.map((e) => (e.payload as NonSharedSliceInSliceZone).key);
|
|
143
162
|
|
|
144
163
|
const onAddNewSlice = () => {
|
|
145
|
-
|
|
164
|
+
setIsUpdateSliceZoneModalOpen(true);
|
|
146
165
|
};
|
|
147
166
|
|
|
148
167
|
const onCreateNewSlice = () => {
|
|
149
168
|
setIsCreateSliceModalOpen(true);
|
|
150
169
|
};
|
|
151
170
|
|
|
171
|
+
const openSlicesTemplatesModal = () => {
|
|
172
|
+
setIsSlicesTemplatesModalOpen(true);
|
|
173
|
+
};
|
|
174
|
+
|
|
152
175
|
return (
|
|
153
176
|
<Box flexDirection="column">
|
|
154
177
|
<List>
|
|
155
178
|
<ListHeader
|
|
156
179
|
actions={
|
|
157
|
-
sliceZone ? (
|
|
158
|
-
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
sliceZone && slicesInSliceZone.length > 0 ? (
|
|
181
|
+
<Box gap={8}>
|
|
182
|
+
<DropdownMenu>
|
|
183
|
+
<DropdownMenuTrigger>
|
|
184
|
+
<Button variant="secondary" startIcon="add">
|
|
185
|
+
Create
|
|
186
|
+
</Button>
|
|
187
|
+
</DropdownMenuTrigger>
|
|
188
|
+
|
|
189
|
+
<DropdownMenuContent align="end">
|
|
190
|
+
<DropdownMenuItem
|
|
191
|
+
startIcon={<Icon name="add" />}
|
|
192
|
+
onSelect={onCreateNewSlice}
|
|
193
|
+
>
|
|
194
|
+
Blank slice
|
|
195
|
+
</DropdownMenuItem>
|
|
196
|
+
|
|
197
|
+
{availableSlicesTemplates.length > 0 ? (
|
|
198
|
+
<DropdownMenuItem
|
|
199
|
+
onSelect={() => {
|
|
200
|
+
openSlicesTemplatesModal();
|
|
201
|
+
}}
|
|
202
|
+
startIcon={<Icon name="centerFocusWeak" />}
|
|
203
|
+
>
|
|
204
|
+
Use a template
|
|
205
|
+
</DropdownMenuItem>
|
|
206
|
+
) : undefined}
|
|
207
|
+
</DropdownMenuContent>
|
|
208
|
+
</DropdownMenu>
|
|
209
|
+
|
|
162
210
|
{availableSlices.length > 0 ? (
|
|
163
211
|
<Button
|
|
164
212
|
data-cy="update-slices"
|
|
165
213
|
onClick={onAddNewSlice}
|
|
166
214
|
startIcon="edit"
|
|
215
|
+
variant="secondary"
|
|
167
216
|
>
|
|
168
|
-
Update
|
|
217
|
+
Update slices
|
|
169
218
|
</Button>
|
|
170
219
|
) : undefined}
|
|
171
|
-
|
|
220
|
+
</Box>
|
|
172
221
|
) : undefined
|
|
173
222
|
}
|
|
174
223
|
toggle={
|
|
@@ -204,12 +253,14 @@ const SliceZone: React.FC<SliceZoneProps> = ({
|
|
|
204
253
|
<SliceZoneBlankSlate
|
|
205
254
|
onAddNewSlice={onAddNewSlice}
|
|
206
255
|
onCreateNewSlice={onCreateNewSlice}
|
|
256
|
+
openSlicesTemplatesModal={openSlicesTemplatesModal}
|
|
207
257
|
projectHasAvailableSlices={availableSlices.length > 0}
|
|
258
|
+
isSlicesTemplatesSupported={availableSlicesTemplates.length > 0}
|
|
208
259
|
/>
|
|
209
260
|
)
|
|
210
261
|
) : undefined}
|
|
211
262
|
<UpdateSliceZoneModal
|
|
212
|
-
isOpen={
|
|
263
|
+
isOpen={isUpdateSliceZoneModalOpen}
|
|
213
264
|
formId={`tab-slicezone-form-${tabId}`}
|
|
214
265
|
availableSlices={availableSlices}
|
|
215
266
|
slicesInSliceZone={sharedSlicesInSliceZone}
|
|
@@ -217,7 +268,36 @@ const SliceZone: React.FC<SliceZoneProps> = ({
|
|
|
217
268
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
218
269
|
onSelectSharedSlices(sliceKeys, nonSharedSlicesKeysInSliceZone)
|
|
219
270
|
}
|
|
220
|
-
close={() =>
|
|
271
|
+
close={() => setIsUpdateSliceZoneModalOpen(false)}
|
|
272
|
+
/>
|
|
273
|
+
<SlicesTemplatesModal
|
|
274
|
+
isOpen={isSlicesTemplatesModalOpen}
|
|
275
|
+
formId={`tab-slicezone-form-${tabId}`}
|
|
276
|
+
availableSlicesTemplates={availableSlicesTemplates}
|
|
277
|
+
onSubmit={({ sliceKeys }) =>
|
|
278
|
+
void createSlicesTemplates({
|
|
279
|
+
templateIDs: sliceKeys,
|
|
280
|
+
localLibrariesNames: localLibraries.map((library) => library.name),
|
|
281
|
+
onSuccess: async (slicesIds: string[]) => {
|
|
282
|
+
// TODO(DT-1453): Remove the need of the global getState
|
|
283
|
+
const serverState = await getState();
|
|
284
|
+
|
|
285
|
+
// Update Redux store
|
|
286
|
+
createSliceSuccess(serverState.libraries);
|
|
287
|
+
|
|
288
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
289
|
+
onSelectSharedSlices(
|
|
290
|
+
slicesIds.concat(
|
|
291
|
+
sharedSlicesInSliceZone.map((s) => s.model.id)
|
|
292
|
+
),
|
|
293
|
+
nonSharedSlicesKeysInSliceZone
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
setIsSlicesTemplatesModalOpen(false);
|
|
297
|
+
},
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
close={() => setIsSlicesTemplatesModalOpen(false)}
|
|
221
301
|
/>
|
|
222
302
|
<DeleteSliceZoneModal
|
|
223
303
|
isDeleteSliceZoneModalOpen={isDeleteSliceZoneModalOpen}
|