slice-machine-ui 1.22.3-beta.1 → 1.22.3-beta.3
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/DeleteVariationModal/index.tsx +12 -11
- package/components/Forms/CreateSliceModal/CreateSliceModal.tsx +2 -5
- package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +9 -5
- package/components/Forms/RenameVariationModal/RenameVariationModal.tsx +12 -11
- package/components/ItemHeader/index.tsx +1 -0
- package/components/ListItem/index.tsx +5 -2
- package/components/ScreenshotChangesModal/VariationDropZone.tsx +31 -9
- package/components/ScreenshotChangesModal/index.tsx +3 -0
- package/components/ScreenshotChangesModal/useCustomScreenshot.tsx +5 -5
- package/components/Simulator/index.tsx +9 -3
- package/lib/builders/CustomTypeBuilder/SliceZone/SlicesTemplatesModal.tsx +2 -2
- package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModal.tsx +2 -2
- package/lib/builders/CustomTypeBuilder/SliceZone/index.tsx +12 -20
- package/lib/builders/CustomTypeBuilder/TabModal/update.tsx +3 -1
- package/lib/builders/CustomTypeBuilder/TabZone/index.tsx +119 -52
- package/lib/builders/CustomTypeBuilder/index.tsx +39 -42
- package/lib/builders/SliceBuilder/FieldZones/index.tsx +81 -56
- package/lib/builders/SliceBuilder/Sidebar/AddVariationModal.tsx +24 -16
- package/lib/builders/SliceBuilder/Sidebar/index.tsx +44 -46
- package/lib/builders/SliceBuilder/SimulatorButton/index.tsx +4 -28
- package/lib/builders/SliceBuilder/index.tsx +10 -96
- package/lib/builders/common/Zone/Card/components/Hints/CodeBlock.tsx +5 -1
- package/lib/builders/common/Zone/Card/components/NewField.tsx +16 -15
- package/lib/builders/common/Zone/Card/index.jsx +2 -0
- package/lib/builders/common/Zone/index.jsx +3 -1
- package/lib/models/common/ComponentUI.ts +0 -14
- package/lib/models/common/CustomType/sliceZone.ts +0 -29
- package/lib/models/common/CustomType/tab.ts +10 -142
- package/lib/models/common/widgets/Group/ListItem/index.jsx +61 -23
- package/out/404.html +1 -1
- package/out/_next/static/chunks/065a3ddb-9a38ca0d60f0bf2f.js +1 -0
- package/out/_next/static/chunks/183-4feb6bb3eddbc768.js +1 -0
- package/out/_next/static/chunks/18539003-7b2711e6c51d6fac.js +97 -0
- package/out/_next/static/chunks/1cc2734a-2c5b6c0367fcde86.js +1 -0
- package/out/_next/static/chunks/25-8fedd33ad9b6de5b.js +1 -0
- package/out/_next/static/chunks/318-541db69860d31138.js +1 -0
- package/out/_next/static/chunks/{505-3f1cf09a086dcba8.js → 376-0ed5822f8afcaa7c.js} +3 -3
- package/out/_next/static/chunks/4c744e84-e3161d754618373f.js +1 -0
- package/out/_next/static/chunks/50-cfc2514205b86001.js +1 -0
- package/out/_next/static/chunks/543-f8766685f7f451e2.js +1 -0
- package/out/_next/static/chunks/59b4e022-7a3b5554b806349f.js +1 -0
- package/out/_next/static/chunks/696-b12edad30a3617e5.js +31 -0
- package/out/_next/static/chunks/727-15cf3f2fea9a37e5.js +1 -0
- package/out/_next/static/chunks/731-501990ebe6a71b32.js +1 -0
- package/out/_next/static/chunks/787-727e3aef5d2a10a8.js +1 -0
- package/out/_next/static/chunks/904-ccd8ca3368ce29fc.js +1 -0
- package/out/_next/static/chunks/{918-38d08f1e885b222d.js → 918-5bb55fb464e34768.js} +1 -1
- package/out/_next/static/chunks/f36c6662-03bb5e9d9aa0b0aa.js +1 -0
- package/out/_next/static/chunks/pages/_app-20876abeebe0fda7.js +430 -0
- package/out/_next/static/chunks/pages/changelog-68d115a14f1423d7.js +1 -0
- package/out/_next/static/chunks/pages/changes-6f62ae7b6243a1c7.js +1 -0
- package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-3a37eb3373bb8823.js → [customTypeId]-3f862ad6111a1fc0.js} +1 -1
- package/out/_next/static/chunks/pages/{custom-types-2f5664d9492b13fb.js → custom-types-94b8f8dbf7727412.js} +1 -1
- package/out/_next/static/chunks/pages/{index-d8e3a2c0d712904f.js → index-64cfb8b0948ba8ef.js} +1 -1
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-733f3890c0466a05.js → [pageTypeId]-d1ffca11c42f2603.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-897ca93c114a1435.js +1 -0
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-e89e2e6f772a3454.js +1 -0
- package/out/_next/static/chunks/pages/slices-9628f8aa54968d6a.js +1 -0
- package/out/_next/static/css/{1bbf650dfd37ce69.css → 1aa04669758c24f4.css} +1 -1
- package/out/_next/static/j_voPTrYzsuLCERqtl3Hn/_buildManifest.js +1 -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/index.html +1 -1
- package/out/labs.html +1 -1
- package/out/page-types/[pageTypeId].html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
- package/out/slices.html +1 -1
- package/package.json +6 -6
- package/pages/slices/[lib]/[sliceName]/[variation]/index.tsx +25 -11
- package/pages/slices/[lib]/[sliceName]/[variation]/simulator.tsx +12 -9
- package/src/apiClient.ts +7 -6
- package/src/components/CodeBlock/CodeBlock.tsx +1 -0
- package/src/components/Window/Window.tsx +7 -1
- package/src/domain/__tests__/customType.test.ts +785 -0
- package/src/domain/customType.ts +519 -6
- package/src/domain/slice.ts +166 -1
- package/src/features/autoSave/AutoSaveStatusIndicator.tsx +43 -0
- package/src/features/autoSave/useAutoSave.tsx +177 -0
- package/src/features/customTypes/EditDropdown.tsx +3 -0
- package/src/features/customTypes/actions/convertCustomToPageType.ts +2 -4
- package/src/features/customTypes/customTypesBuilder/CustomTypeProvider.tsx +90 -0
- package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +46 -79
- package/src/features/customTypes/customTypesMessages.ts +4 -0
- package/src/features/slices/actions/addSlicesToSliceZone.ts +2 -7
- package/src/features/slices/actions/uploadSliceScreenshot.ts +45 -0
- package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx +5 -5
- package/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx +4 -10
- package/src/features/slices/sliceBuilder/SliceBuilderProvider.tsx +110 -0
- package/src/features/slices/sliceBuilder/actions/deleteVariation.ts +8 -24
- package/src/features/slices/sliceBuilder/actions/renameVariation.ts +8 -24
- package/src/features/slices/sliceCards/SharedSliceCard.tsx +1 -0
- package/src/hooks/useCurrentSlice.tsx +4 -16
- package/src/hooks/useScreenshotChangesModal.ts +1 -0
- package/src/hooks/useServerState.ts +1 -58
- package/src/modules/availableCustomTypes/index.ts +8 -3
- package/src/modules/simulator/index.ts +0 -2
- package/src/modules/slices/index.ts +32 -25
- package/src/modules/slices/selector.ts +30 -0
- package/src/modules/useSliceMachineActions.ts +20 -270
- package/src/redux/reducer.ts +0 -4
- package/src/redux/saga.ts +0 -6
- package/src/redux/type.ts +0 -4
- package/test/src/modules/availableCustomTypes/index.test.ts +8 -10
- package/test/src/modules/simulator.test.ts +0 -2
- package/lib/models/common/CustomType/group.ts +0 -80
- package/lib/models/common/Variation.ts +0 -100
- package/out/_next/static/ZrWICkLApT4ZATA_akn-2/_buildManifest.js +0 -1
- package/out/_next/static/chunks/18539003-4460ccbfe3109578.js +0 -97
- package/out/_next/static/chunks/482-34cee2a2071c235f.js +0 -1
- package/out/_next/static/chunks/550-c80fd46fb64d1eef.js +0 -1
- package/out/_next/static/chunks/80-7b8a97d0122ff74a.js +0 -1
- package/out/_next/static/chunks/840-163f8a1040e6820d.js +0 -1
- package/out/_next/static/chunks/904-519dbf0f7e8c6243.js +0 -1
- package/out/_next/static/chunks/958-8aca174b80cb0c35.js +0 -1
- package/out/_next/static/chunks/pages/_app-132564608e9a9502.js +0 -458
- package/out/_next/static/chunks/pages/changelog-4d0f2f1222e403fe.js +0 -1
- package/out/_next/static/chunks/pages/changes-52c9d917808d1461.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-7b17cb59d0db03b5.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-ef11594ce026b650.js +0 -1
- package/out/_next/static/chunks/pages/slices-884a936a9a062a65.js +0 -1
- package/src/domain/__tests__/CustomTypeModel.test.ts +0 -247
- package/src/layouts/WithSlice.tsx +0 -26
- package/src/modules/screenshots/actions.ts +0 -21
- package/src/modules/screenshots/sagas.ts +0 -70
- package/src/modules/selectedCustomType/actions.ts +0 -147
- package/src/modules/selectedCustomType/index.ts +0 -11
- package/src/modules/selectedCustomType/reducer.ts +0 -287
- package/src/modules/selectedCustomType/sagas.ts +0 -72
- package/src/modules/selectedCustomType/selectors.ts +0 -33
- package/src/modules/selectedCustomType/stateHelpers.ts +0 -42
- package/src/modules/selectedCustomType/types.ts +0 -9
- package/src/modules/selectedSlice/actions.ts +0 -106
- package/src/modules/selectedSlice/reducer.ts +0 -175
- package/src/modules/selectedSlice/sagas.ts +0 -72
- package/src/modules/selectedSlice/selectors.ts +0 -55
- package/src/modules/selectedSlice/types.ts +0 -3
- package/src/modules/toaster/utils.tsx +0 -23
- package/test/lib/models/common/CustomType/sliceZone.test.ts +0 -49
- package/test/pages/custom-types.test.tsx +0 -625
- package/test/src/modules/selectedCustomType/__fixtures__/model.json +0 -119
- package/test/src/modules/selectedCustomType/reducer.test.ts +0 -322
- package/test/src/modules/selectedCustomType/sagas.test.ts +0 -89
- package/test/src/modules/selectedCustomType/selectors.test.ts +0 -54
- package/test/src/modules/selectedSlice/__fixtures__/mocks.json +0 -171
- package/test/src/modules/selectedSlice/__fixtures__/model.json +0 -35
- package/test/src/modules/selectedSlice/__testutils__/getRefreshStateCreatorPayloadData.ts +0 -72
- package/test/src/modules/selectedSlice/__testutils__/getSelectedSliceDummyData.ts +0 -30
- package/test/src/modules/selectedSlice/reducer.test.ts +0 -170
- package/test/src/modules/selectedSlice/sagas.test.ts +0 -82
- package/test/src/modules/toaster/utils.test.ts +0 -50
- /package/out/_next/static/{ZrWICkLApT4ZATA_akn-2 → j_voPTrYzsuLCERqtl3Hn}/_ssgManifest.js +0 -0
|
@@ -1,67 +1,74 @@
|
|
|
1
1
|
import { Box, ErrorBoundary, ProgressCircle } from "@prismicio/editor-ui";
|
|
2
2
|
import { FC, Suspense } from "react";
|
|
3
|
+
import { flushSync } from "react-dom";
|
|
3
4
|
import type { DropResult } from "react-beautiful-dnd";
|
|
4
|
-
import { useSelector } from "react-redux";
|
|
5
5
|
import type { AnyObjectSchema } from "yup";
|
|
6
6
|
import { useRouter } from "next/router";
|
|
7
7
|
|
|
8
8
|
import ctBuilderArray from "@lib/models/common/widgets/ctBuilderArray";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
TabField,
|
|
12
|
-
TabFields,
|
|
9
|
+
import {
|
|
10
|
+
TabSM,
|
|
11
|
+
type TabField,
|
|
12
|
+
type TabFields,
|
|
13
|
+
CustomTypes,
|
|
14
|
+
TabFieldsModel,
|
|
13
15
|
} from "@lib/models/common/CustomType";
|
|
14
|
-
import type {
|
|
16
|
+
import type { AnyWidget } from "@lib/models/common/widgets/Widget";
|
|
15
17
|
import { ensureDnDDestination, ensureWidgetTypeExistence } from "@lib/utils";
|
|
16
18
|
import { List } from "@src/components/List";
|
|
17
|
-
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
18
|
-
import type { SliceMachineStoreType } from "@src/redux/type";
|
|
19
19
|
import { telemetry } from "@src/apiClient";
|
|
20
20
|
import { transformKeyAccessor } from "@utils/str";
|
|
21
|
+
import { useCustomTypeState } from "@src/features/customTypes/customTypesBuilder/CustomTypeProvider";
|
|
22
|
+
import {
|
|
23
|
+
createSectionSliceZone,
|
|
24
|
+
deleteSectionSliceZone,
|
|
25
|
+
deleteSliceZoneSlice,
|
|
26
|
+
addField,
|
|
27
|
+
deleteField,
|
|
28
|
+
reorderField,
|
|
29
|
+
updateField,
|
|
30
|
+
} from "@src/domain/customType";
|
|
21
31
|
|
|
22
32
|
import * as Widgets from "../../../../lib/models/common/widgets/withGroup";
|
|
23
|
-
import { selectCurrentPoolOfFields } from "../../../../src/modules/selectedCustomType";
|
|
24
|
-
import type { Widget } from "../../../models/common/widgets/Widget";
|
|
25
33
|
import EditModal from "../../common/EditModal";
|
|
26
34
|
import Zone from "../../common/Zone";
|
|
27
35
|
import SliceZone from "../SliceZone";
|
|
36
|
+
import {
|
|
37
|
+
Group,
|
|
38
|
+
NestableWidget,
|
|
39
|
+
UID,
|
|
40
|
+
} from "@prismicio/types-internal/lib/customtypes";
|
|
28
41
|
|
|
29
42
|
interface TabZoneProps {
|
|
30
|
-
customType: CustomTypeSM;
|
|
31
43
|
tabId: string;
|
|
32
|
-
sliceZone?: SlicesSM | null | undefined;
|
|
33
|
-
fields: TabFields;
|
|
34
44
|
}
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
customType,
|
|
38
|
-
tabId,
|
|
39
|
-
fields,
|
|
40
|
-
sliceZone,
|
|
41
|
-
}) => {
|
|
42
|
-
const {
|
|
43
|
-
deleteCustomTypeField,
|
|
44
|
-
addCustomTypeField,
|
|
45
|
-
reorderCustomTypeField,
|
|
46
|
-
replaceCustomTypeField,
|
|
47
|
-
createSliceZone,
|
|
48
|
-
deleteSliceZone,
|
|
49
|
-
deleteCustomTypeSharedSlice,
|
|
50
|
-
} = useSliceMachineActions();
|
|
46
|
+
type PoolOfFields = ReadonlyArray<{ key: string; value: TabField }>;
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
const TabZone: FC<TabZoneProps> = ({ tabId }) => {
|
|
49
|
+
const { customType, setCustomType } = useCustomTypeState();
|
|
50
|
+
const customTypeSM = CustomTypes.toSM(customType);
|
|
51
|
+
const sliceZone = customTypeSM.tabs.find((tab) => tab.key === tabId)
|
|
52
|
+
?.sliceZone;
|
|
53
|
+
const fields: TabFields =
|
|
54
|
+
customTypeSM.tabs.find((tab) => tab.key === tabId)?.value ?? [];
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
const { query } = useRouter();
|
|
57
|
+
const poolOfFields = customTypeSM.tabs.reduce<PoolOfFields>(
|
|
58
|
+
(acc: PoolOfFields, curr: TabSM) => {
|
|
59
|
+
return [...acc, ...curr.value];
|
|
60
|
+
},
|
|
61
|
+
[],
|
|
62
|
+
);
|
|
62
63
|
|
|
63
64
|
const onDeleteItem = (fieldId: string) => {
|
|
64
|
-
|
|
65
|
+
const newCustomType = deleteField({
|
|
66
|
+
customType,
|
|
67
|
+
fieldId,
|
|
68
|
+
sectionId: tabId,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
setCustomType(newCustomType);
|
|
65
72
|
};
|
|
66
73
|
|
|
67
74
|
const onSaveNewField = ({
|
|
@@ -80,27 +87,67 @@ const TabZone: FC<TabZoneProps> = ({
|
|
|
80
87
|
// @ts-expect-error We have to create a widget map or a service instead of using export name
|
|
81
88
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
82
89
|
const widget: Widget<TabField, AnyObjectSchema> = Widgets[widgetTypeName];
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
|
|
91
|
+
const field: TabField = widget.create(label);
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
field.type === "Range" ||
|
|
95
|
+
field.type === "IntegrationFields" ||
|
|
96
|
+
field.type === "Separator"
|
|
97
|
+
) {
|
|
98
|
+
throw new Error(`Unsupported Field Type: ${field.type}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const CurrentWidget: AnyWidget = Widgets[field.type];
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
105
|
+
CurrentWidget.schema.validateSync(field, { stripUnknown: false });
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw new Error(`Add field: Model is invalid for field "${field.type}".`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const newField: NestableWidget | UID | Group = TabFieldsModel.fromSM(field);
|
|
111
|
+
const newCustomType = addField({
|
|
112
|
+
customType,
|
|
113
|
+
newField,
|
|
114
|
+
newFieldId: id,
|
|
115
|
+
sectionId: tabId,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
setCustomType(newCustomType);
|
|
119
|
+
|
|
83
120
|
void telemetry.track({
|
|
84
121
|
event: "custom-type:field-added",
|
|
85
122
|
id,
|
|
86
123
|
name: customType.id,
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
|
87
125
|
type: widget.TYPE_NAME,
|
|
88
126
|
zone: "static",
|
|
89
127
|
});
|
|
90
|
-
addCustomTypeField(tabId, id, widget.create(label));
|
|
91
128
|
};
|
|
92
129
|
|
|
93
130
|
const onDragEnd = (result: DropResult) => {
|
|
94
131
|
if (ensureDnDDestination(result)) {
|
|
95
132
|
return;
|
|
96
133
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
134
|
+
|
|
135
|
+
const { source, destination } = result;
|
|
136
|
+
if (!destination) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const newCustomType = reorderField({
|
|
141
|
+
customType,
|
|
142
|
+
sourceIndex: source.index,
|
|
143
|
+
destinationIndex: destination.index,
|
|
144
|
+
sectionId: tabId,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// When removing redux and replacing it by a simple useState, react-beautiful-dnd (that is deprecated library) was making the fields flickering on reorder.
|
|
148
|
+
// The problem seems to come from the react non-synchronous way to handle our state update that didn't work well with the library.
|
|
149
|
+
// It's a hack and since it's used on an old pure JavaScript code with a deprecated library it will be removed when updating the UI of the fields.
|
|
150
|
+
flushSync(() => setCustomType(newCustomType));
|
|
104
151
|
};
|
|
105
152
|
|
|
106
153
|
const onSave = ({
|
|
@@ -117,19 +164,39 @@ const TabZone: FC<TabZoneProps> = ({
|
|
|
117
164
|
if (ensureWidgetTypeExistence(Widgets, value.type)) {
|
|
118
165
|
return;
|
|
119
166
|
}
|
|
120
|
-
|
|
167
|
+
|
|
168
|
+
const newField: NestableWidget | UID | Group = TabFieldsModel.fromSM(value);
|
|
169
|
+
const newCustomType = updateField({
|
|
170
|
+
customType,
|
|
171
|
+
previousFieldId: previousKey,
|
|
172
|
+
newFieldId: newKey,
|
|
173
|
+
newField,
|
|
174
|
+
sectionId: tabId,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
setCustomType(newCustomType);
|
|
121
178
|
};
|
|
122
179
|
|
|
123
180
|
const onCreateSliceZone = () => {
|
|
124
|
-
|
|
181
|
+
const newCustomType = createSectionSliceZone(customType, tabId);
|
|
182
|
+
|
|
183
|
+
setCustomType(newCustomType);
|
|
125
184
|
};
|
|
126
185
|
|
|
127
186
|
const onDeleteSliceZone = () => {
|
|
128
|
-
|
|
187
|
+
const newCustomType = deleteSectionSliceZone(customType, tabId);
|
|
188
|
+
|
|
189
|
+
setCustomType(newCustomType);
|
|
129
190
|
};
|
|
130
191
|
|
|
131
192
|
const onRemoveSharedSlice = (sliceId: string) => {
|
|
132
|
-
|
|
193
|
+
const newCustomType = deleteSliceZoneSlice({
|
|
194
|
+
customType,
|
|
195
|
+
sectionId: tabId,
|
|
196
|
+
sliceId,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
setCustomType(newCustomType);
|
|
133
200
|
};
|
|
134
201
|
|
|
135
202
|
return (
|
|
@@ -169,13 +236,13 @@ const TabZone: FC<TabZoneProps> = ({
|
|
|
169
236
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument
|
|
170
237
|
`data${transformKeyAccessor(key)}`
|
|
171
238
|
}
|
|
172
|
-
dataCy="
|
|
239
|
+
dataCy="static-zone-content"
|
|
173
240
|
isRepeatableCustomType={customType.repeatable}
|
|
174
241
|
/>
|
|
175
242
|
) : undefined}
|
|
176
243
|
|
|
177
244
|
<SliceZone
|
|
178
|
-
customType={
|
|
245
|
+
customType={customTypeSM}
|
|
179
246
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
180
247
|
tabId={tabId}
|
|
181
248
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { DropdownMenuItem, Icon } from "@prismicio/editor-ui";
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from "react";
|
|
3
3
|
import { useRouter } from "next/router";
|
|
4
4
|
|
|
5
|
-
import type { CustomTypeSM } from "@lib/models/common/CustomType";
|
|
6
5
|
import {
|
|
7
6
|
Window,
|
|
8
7
|
WindowFrame,
|
|
@@ -11,33 +10,35 @@ import {
|
|
|
11
10
|
WindowTabsList,
|
|
12
11
|
WindowTabsTrigger,
|
|
13
12
|
} from "@src/components/Window";
|
|
14
|
-
import
|
|
13
|
+
import { useCustomTypeState } from "@src/features/customTypes/customTypesBuilder/CustomTypeProvider";
|
|
14
|
+
import { CustomTypes } from "@lib/models/common/CustomType";
|
|
15
|
+
import {
|
|
16
|
+
createSection,
|
|
17
|
+
deleteSection,
|
|
18
|
+
renameSection,
|
|
19
|
+
} from "@src/domain/customType";
|
|
15
20
|
|
|
16
21
|
import CreateModal from "./TabModal/create";
|
|
17
22
|
import DeleteModal from "./TabModal/delete";
|
|
18
23
|
import UpdateModal from "./TabModal/update";
|
|
19
24
|
import TabZone from "./TabZone";
|
|
20
25
|
|
|
21
|
-
type CustomTypeBuilderProps = { customType: CustomTypeSM };
|
|
22
|
-
|
|
23
26
|
type DialogState =
|
|
24
|
-
| { type: "
|
|
25
|
-
| { type: "
|
|
26
|
-
| { type: "
|
|
27
|
+
| { type: "CREATE_CUSTOM_TYPE_TAB" }
|
|
28
|
+
| { type: "UPDATE_CUSTOM_TYPE_TAB"; tabKey: string }
|
|
29
|
+
| { type: "DELETE_CUSTOM_TYPE_TAB"; tabKey: string }
|
|
27
30
|
| undefined;
|
|
28
31
|
|
|
29
|
-
export const CustomTypeBuilder
|
|
30
|
-
const { customType } =
|
|
31
|
-
|
|
32
|
-
const [tabValue, setTabValue] = useState(
|
|
32
|
+
export const CustomTypeBuilder = () => {
|
|
33
|
+
const { customType, setCustomType } = useCustomTypeState();
|
|
34
|
+
const customTypeSM = CustomTypes.toSM(customType);
|
|
35
|
+
const [tabValue, setTabValue] = useState(customTypeSM.tabs[0]?.key);
|
|
33
36
|
|
|
34
37
|
const [dialog, setDialog] = useState<DialogState>();
|
|
35
|
-
const { createCustomTypeTab, updateCustomTypeTab, deleteCustomTypeTab } =
|
|
36
|
-
useSliceMachineActions();
|
|
37
38
|
|
|
38
39
|
const { query } = useRouter();
|
|
39
40
|
const sliceZoneEmpty =
|
|
40
|
-
|
|
41
|
+
customTypeSM.tabs.find((tab) => tab.key === tabValue)?.sliceZone?.value
|
|
41
42
|
.length === 0;
|
|
42
43
|
|
|
43
44
|
return (
|
|
@@ -45,20 +46,15 @@ export const CustomTypeBuilder: FC<CustomTypeBuilderProps> = (props) => {
|
|
|
45
46
|
<Window style={sliceZoneEmpty ? { flexGrow: 1 } : undefined}>
|
|
46
47
|
{customType.format === "page" ? <WindowFrame /> : undefined}
|
|
47
48
|
{query.newPageType === "true" ? (
|
|
48
|
-
<TabZone
|
|
49
|
-
customType={customType}
|
|
50
|
-
fields={customType.tabs[0].value}
|
|
51
|
-
sliceZone={customType.tabs[0].sliceZone}
|
|
52
|
-
tabId={customType.tabs[0].key}
|
|
53
|
-
/>
|
|
49
|
+
<TabZone tabId={customTypeSM.tabs[0].key} />
|
|
54
50
|
) : (
|
|
55
51
|
<WindowTabs onValueChange={setTabValue} value={tabValue}>
|
|
56
52
|
<WindowTabsList
|
|
57
53
|
onAddNewTab={() => {
|
|
58
|
-
setDialog({ type: "
|
|
54
|
+
setDialog({ type: "CREATE_CUSTOM_TYPE_TAB" });
|
|
59
55
|
}}
|
|
60
56
|
>
|
|
61
|
-
{
|
|
57
|
+
{customTypeSM.tabs.map((tab) => (
|
|
62
58
|
<WindowTabsTrigger
|
|
63
59
|
key={tab.key}
|
|
64
60
|
menu={
|
|
@@ -66,7 +62,7 @@ export const CustomTypeBuilder: FC<CustomTypeBuilderProps> = (props) => {
|
|
|
66
62
|
<DropdownMenuItem
|
|
67
63
|
onSelect={() => {
|
|
68
64
|
setDialog({
|
|
69
|
-
type: "
|
|
65
|
+
type: "UPDATE_CUSTOM_TYPE_TAB",
|
|
70
66
|
tabKey: tab.key,
|
|
71
67
|
});
|
|
72
68
|
}}
|
|
@@ -76,10 +72,10 @@ export const CustomTypeBuilder: FC<CustomTypeBuilderProps> = (props) => {
|
|
|
76
72
|
</DropdownMenuItem>
|
|
77
73
|
<DropdownMenuItem
|
|
78
74
|
color="tomato"
|
|
79
|
-
disabled={
|
|
75
|
+
disabled={customTypeSM.tabs.length <= 1}
|
|
80
76
|
onSelect={() => {
|
|
81
77
|
setDialog({
|
|
82
|
-
type: "
|
|
78
|
+
type: "DELETE_CUSTOM_TYPE_TAB",
|
|
83
79
|
tabKey: tab.key,
|
|
84
80
|
});
|
|
85
81
|
}}
|
|
@@ -95,57 +91,58 @@ export const CustomTypeBuilder: FC<CustomTypeBuilderProps> = (props) => {
|
|
|
95
91
|
</WindowTabsTrigger>
|
|
96
92
|
))}
|
|
97
93
|
</WindowTabsList>
|
|
98
|
-
{
|
|
94
|
+
{customTypeSM.tabs.map((tab) => (
|
|
99
95
|
<WindowTabsContent key={tab.key} value={tab.key}>
|
|
100
|
-
<TabZone
|
|
101
|
-
customType={customType}
|
|
102
|
-
fields={tab.value}
|
|
103
|
-
sliceZone={tab.sliceZone}
|
|
104
|
-
tabId={tab.key}
|
|
105
|
-
/>
|
|
96
|
+
<TabZone tabId={tab.key} />
|
|
106
97
|
</WindowTabsContent>
|
|
107
98
|
))}
|
|
108
99
|
</WindowTabs>
|
|
109
100
|
)}
|
|
110
101
|
</Window>
|
|
111
|
-
{dialog?.type === "
|
|
102
|
+
{dialog?.type === "CREATE_CUSTOM_TYPE_TAB" ? (
|
|
112
103
|
<CreateModal
|
|
113
104
|
close={() => {
|
|
114
105
|
setDialog(undefined);
|
|
115
106
|
}}
|
|
116
107
|
isOpen
|
|
117
108
|
onSubmit={({ id }) => {
|
|
118
|
-
|
|
109
|
+
const newCustomType = createSection(customType, id);
|
|
110
|
+
setCustomType(newCustomType);
|
|
119
111
|
setTabValue(id);
|
|
120
112
|
}}
|
|
121
|
-
tabIds={
|
|
113
|
+
tabIds={customTypeSM.tabs.map((tab) => tab.key.toLowerCase())}
|
|
122
114
|
/>
|
|
123
115
|
) : undefined}
|
|
124
|
-
{dialog?.type === "
|
|
116
|
+
{dialog?.type === "UPDATE_CUSTOM_TYPE_TAB" ? (
|
|
125
117
|
<UpdateModal
|
|
126
118
|
close={() => {
|
|
127
119
|
setDialog(undefined);
|
|
128
120
|
}}
|
|
121
|
+
initialTabKey={dialog.tabKey}
|
|
129
122
|
isOpen
|
|
130
123
|
onSubmit={({ id }) => {
|
|
131
|
-
|
|
124
|
+
const newCustomType = renameSection(customType, dialog.tabKey, id);
|
|
125
|
+
setCustomType(newCustomType);
|
|
126
|
+
|
|
132
127
|
if (tabValue === dialog.tabKey) setTabValue(id);
|
|
133
128
|
}}
|
|
134
|
-
tabIds={
|
|
129
|
+
tabIds={customTypeSM.tabs
|
|
135
130
|
.filter((tab) => tab.key !== dialog.tabKey)
|
|
136
131
|
.map((tab) => tab.key.toLowerCase())}
|
|
137
132
|
/>
|
|
138
133
|
) : undefined}
|
|
139
|
-
{dialog?.type === "
|
|
134
|
+
{dialog?.type === "DELETE_CUSTOM_TYPE_TAB" ? (
|
|
140
135
|
<DeleteModal
|
|
141
136
|
close={() => {
|
|
142
137
|
setDialog(undefined);
|
|
143
138
|
}}
|
|
144
139
|
isOpen
|
|
145
140
|
onSubmit={() => {
|
|
146
|
-
|
|
141
|
+
const newCustomType = deleteSection(customType, dialog.tabKey);
|
|
142
|
+
setCustomType(newCustomType);
|
|
143
|
+
|
|
147
144
|
if (tabValue === dialog.tabKey) {
|
|
148
|
-
const otherTabValue =
|
|
145
|
+
const otherTabValue = customTypeSM.tabs.find(
|
|
149
146
|
(tab) => tab.key !== dialog.tabKey,
|
|
150
147
|
)?.key;
|
|
151
148
|
if (otherTabValue !== undefined) setTabValue(otherTabValue);
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { flushSync } from "react-dom";
|
|
3
|
+
import { DropResult } from "react-beautiful-dnd";
|
|
4
|
+
import { NestableWidget } from "@prismicio/types-internal/lib/customtypes";
|
|
5
|
+
|
|
1
6
|
import { ensureDnDDestination } from "@lib/utils";
|
|
2
7
|
import { transformKeyAccessor } from "@utils/str";
|
|
3
|
-
|
|
4
|
-
import Zone from "../../common/Zone";
|
|
5
|
-
import EditModal from "../../common/EditModal";
|
|
6
|
-
|
|
7
8
|
import * as Widgets from "@lib/models/common/widgets";
|
|
8
9
|
import sliceBuilderWidgetsArray from "@lib/models/common/widgets/sliceBuilderArray";
|
|
9
|
-
|
|
10
|
-
import { DropResult } from "react-beautiful-dnd";
|
|
11
10
|
import { List } from "@src/components/List";
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
import { WidgetsArea } from "@lib/models/common/Slice";
|
|
12
|
+
import { useSliceState } from "@src/features/slices/sliceBuilder/SliceBuilderProvider";
|
|
13
|
+
import {
|
|
14
|
+
addField,
|
|
15
|
+
deleteField,
|
|
16
|
+
reorderField,
|
|
17
|
+
updateField,
|
|
18
|
+
} from "@src/domain/slice";
|
|
19
|
+
import Zone from "@lib/builders/common/Zone";
|
|
20
|
+
import EditModal from "@lib/builders/common/EditModal";
|
|
21
|
+
import { AnyWidget } from "@lib/models/common/widgets/Widget";
|
|
16
22
|
|
|
17
23
|
const dataTipText = ` The non-repeatable zone
|
|
18
24
|
is for fields<br/> that should appear once, like a<br/>
|
|
@@ -22,24 +28,18 @@ const dataTipText2 = `The repeatable zone is for a group<br/>
|
|
|
22
28
|
of fields that you want to be able to repeat an<br/>
|
|
23
29
|
indeterminate number of times, like FAQs`;
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
variation
|
|
27
|
-
};
|
|
31
|
+
const FieldZones: FC = () => {
|
|
32
|
+
const { slice, setSlice, variation } = useSliceState();
|
|
28
33
|
|
|
29
|
-
const FieldZones: React.FunctionComponent<FieldZonesProps> = ({
|
|
30
|
-
variation,
|
|
31
|
-
}) => {
|
|
32
|
-
const {
|
|
33
|
-
addSliceWidget,
|
|
34
|
-
replaceSliceWidget,
|
|
35
|
-
reorderSliceWidget,
|
|
36
|
-
removeSliceWidget,
|
|
37
|
-
updateSliceWidgetMock,
|
|
38
|
-
deleteSliceWidgetMock,
|
|
39
|
-
} = useSliceMachineActions();
|
|
40
34
|
const _onDeleteItem = (widgetArea: WidgetsArea) => (key: string) => {
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
const newSlice = deleteField({
|
|
36
|
+
slice,
|
|
37
|
+
variationId: variation.id,
|
|
38
|
+
widgetArea,
|
|
39
|
+
fieldId: key,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
setSlice(newSlice);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const _onSave =
|
|
@@ -48,30 +48,23 @@ const FieldZones: React.FunctionComponent<FieldZonesProps> = ({
|
|
|
48
48
|
apiId: previousKey,
|
|
49
49
|
newKey,
|
|
50
50
|
value,
|
|
51
|
-
mockValue,
|
|
52
51
|
}: {
|
|
53
52
|
apiId: string;
|
|
54
53
|
newKey: string;
|
|
55
54
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
55
|
value: any;
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
-
mockValue: any;
|
|
59
56
|
}) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
deleteSliceWidgetMock(variation.id, widgetArea, newKey);
|
|
72
|
-
}
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
74
|
-
replaceSliceWidget(variation.id, widgetArea, previousKey, newKey, value);
|
|
57
|
+
const newSlice = updateField({
|
|
58
|
+
slice,
|
|
59
|
+
variationId: variation.id,
|
|
60
|
+
widgetArea,
|
|
61
|
+
previousFieldId: previousKey,
|
|
62
|
+
newFieldId: newKey,
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
64
|
+
newField: value,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
setSlice(newSlice);
|
|
75
68
|
};
|
|
76
69
|
|
|
77
70
|
const _onSaveNewField =
|
|
@@ -96,24 +89,56 @@ const FieldZones: React.FunctionComponent<FieldZonesProps> = ({
|
|
|
96
89
|
);
|
|
97
90
|
}
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
93
|
+
const newField = widget.create(label) as NestableWidget;
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
newField.type === "Range" ||
|
|
97
|
+
newField.type === "IntegrationFields" ||
|
|
98
|
+
newField.type === "Separator"
|
|
99
|
+
) {
|
|
100
|
+
throw new Error(`Unsupported Field Type: ${newField.type}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const CurrentWidget: AnyWidget = Widgets[newField.type];
|
|
103
105
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
+
CurrentWidget.schema.validateSync(newField, { stripUnknown: false });
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw new Error(`Model is invalid for widget "${newField.type}".`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const newSlice = addField({
|
|
112
|
+
slice,
|
|
113
|
+
variationId: variation.id,
|
|
114
|
+
widgetArea,
|
|
115
|
+
newFieldId: id,
|
|
116
|
+
newField,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
setSlice(newSlice);
|
|
106
120
|
};
|
|
107
121
|
|
|
108
122
|
const _onDragEnd = (widgetArea: WidgetsArea) => (result: DropResult) => {
|
|
109
123
|
if (ensureDnDDestination(result)) return;
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
125
|
+
const { source, destination } = result;
|
|
126
|
+
if (!destination) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const newSlice = reorderField({
|
|
131
|
+
slice,
|
|
132
|
+
variationId: variation.id,
|
|
113
133
|
widgetArea,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
);
|
|
134
|
+
sourceIndex: source.index,
|
|
135
|
+
destinationIndex: destination.index,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// When removing redux and replacing it by a simple useState, react-beautiful-dnd (that is deprecated library) was making the fields flickering on reorder.
|
|
139
|
+
// The problem seems to come from the react non-synchronous way to handle our state update that didn't work well with the library.
|
|
140
|
+
// It's a hack and since it's used on an old pure JavaScript code with a deprecated library it will be removed when updating the UI of the fields.
|
|
141
|
+
flushSync(() => setSlice(newSlice));
|
|
117
142
|
};
|
|
118
143
|
|
|
119
144
|
return (
|
|
@@ -141,7 +166,7 @@ const FieldZones: React.FunctionComponent<FieldZonesProps> = ({
|
|
|
141
166
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
142
167
|
`slice.primary${transformKeyAccessor(key)}`
|
|
143
168
|
}
|
|
144
|
-
dataCy="
|
|
169
|
+
dataCy="static-zone-content"
|
|
145
170
|
isRepeatableCustomType={undefined}
|
|
146
171
|
/>
|
|
147
172
|
<Zone
|