slice-machine-ui 1.19.3-dev-next-release.3 → 1.19.3-dev-environments.6
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/AppLayout/index.tsx +34 -10
- package/components/Navigation/Environment.tsx +47 -0
- package/components/Navigation/index.css.ts +6 -0
- package/components/Navigation/index.tsx +15 -2
- package/lib/builders/SliceBuilder/Sidebar/{AddVariationModal.tsx → VariationModal.tsx} +3 -3
- package/lib/builders/SliceBuilder/Sidebar/index.tsx +13 -52
- package/lib/builders/SliceBuilder/index.tsx +27 -31
- package/out/404.html +1 -1
- package/out/_next/static/{0Lwj5aWsM8JhkX_oWgDHj → SPaOafYlpiOTCKrKML7gk}/_buildManifest.js +1 -1
- package/out/_next/static/chunks/840-5b485c737b24324b.js +1 -0
- package/out/_next/static/chunks/904-e290f0254cc4b5df.js +1 -0
- package/out/_next/static/chunks/{958-c90d60818f1c468a.js → 958-be627006594efb21.js} +1 -1
- package/out/_next/static/chunks/pages/{_app-d42e615a839b8752.js → _app-2af35c541ee1bab0.js} +7 -7
- package/out/_next/static/chunks/pages/{changelog-fa36b9995c26e1d7.js → changelog-4b8369d91d82b28b.js} +1 -1
- package/out/_next/static/chunks/pages/changes-db6e8c6be5ae076e.js +1 -0
- package/out/_next/static/chunks/pages/labs-2922105ab714d32a.js +1 -0
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-ca780766d02c801b.js +1 -0
- package/out/_next/static/chunks/pages/slices-93b7af2624c85b8e.js +1 -0
- package/out/_next/static/css/{412af4286eb0b283.css → 009bd7f5ac85fc6a.css} +1 -1
- 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 +4 -4
- package/pages/slices.tsx +1 -0
- package/src/apiClient.ts +4 -32
- package/src/components/Divider/Divider.css.ts +31 -0
- package/src/components/Divider/Divider.stories.tsx +27 -0
- package/src/components/Divider/Divider.tsx +25 -0
- package/src/components/Divider/index.ts +1 -0
- package/src/components/PageLayout/PageLayout.css.ts +8 -3
- package/src/components/PageLayout/PageLayout.stories.tsx +10 -1
- package/src/components/PageLayout/PageLayout.tsx +7 -2
- package/src/components/SideNav/SideNav.css.ts +3 -10
- package/src/components/SideNav/SideNav.stories.tsx +29 -2
- package/src/components/SideNav/SideNav.tsx +5 -1
- package/src/components/SideNav/SideNavEnvironmentSelector.css.ts +69 -0
- package/src/components/SideNav/SideNavEnvironmentSelector.tsx +163 -0
- package/src/components/SideNav/index.ts +1 -0
- package/src/features/customTypes/__tests__/CustomTypeBuilderPage.test.tsx +4 -3
- package/src/features/environments/actions/getActiveEnvironmentDomain.ts +11 -0
- package/src/features/environments/actions/getEnvironments.ts +12 -0
- package/src/features/environments/actions/setEnvironment.ts +18 -0
- package/src/features/environments/useActiveEnvironment.ts +38 -0
- package/src/features/environments/useEnvironments.ts +7 -0
- package/src/features/legacyState/actions/getLegacySliceMachineState.ts +53 -0
- package/src/features/legacyState/useLegacySliceMachineState.ts +7 -0
- package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx +4 -3
- package/src/features/slices/sliceCards/SharedSliceCard.tsx +17 -44
- package/src/modules/environment/index.ts +2 -2
- package/src/modules/screenshots/sagas.ts +6 -3
- package/src/modules/selectedSlice/actions.ts +2 -7
- package/src/modules/selectedSlice/reducer.ts +1 -6
- package/src/modules/selectedSlice/sagas.ts +18 -10
- package/src/modules/slices/index.ts +1 -23
- package/src/modules/toaster/utils.tsx +12 -6
- package/src/modules/useSliceMachineActions.ts +3 -9
- package/test/pages/slices.test.tsx +4 -8
- package/test/src/modules/__fixtures__/serverState.ts +2 -0
- package/test/src/modules/selectedSlice/sagas.test.ts +12 -14
- package/test/src/modules/toaster/utils.test.ts +34 -3
- package/components/DeleteVariationModal/index.tsx +0 -83
- package/components/Forms/RenameVariationModal/RenameVariationModal.css.ts +0 -7
- package/components/Forms/RenameVariationModal/RenameVariationModal.tsx +0 -117
- package/components/Forms/RenameVariationModal/index.ts +0 -1
- package/out/_next/static/chunks/840-884e41a48b92e5d3.js +0 -1
- package/out/_next/static/chunks/904-69cc3c4be2bff626.js +0 -1
- package/out/_next/static/chunks/pages/changes-e388be4457a43c3a.js +0 -1
- package/out/_next/static/chunks/pages/labs-ebce03a4e7a95a4e.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-7c811c2c79f01a25.js +0 -1
- package/out/_next/static/chunks/pages/slices-22db04643850c1d8.js +0 -1
- package/src/features/slices/sliceBuilder/actions/deleteVariation.ts +0 -86
- package/src/features/slices/sliceBuilder/actions/renameVariation.ts +0 -80
- /package/out/_next/static/{0Lwj5aWsM8JhkX_oWgDHj → SPaOafYlpiOTCKrKML7gk}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import ServerState from "@models/server/ServerState";
|
|
2
|
+
import { Slices } from "@lib/models/common/Slice";
|
|
3
|
+
import { CustomTypes } from "@lib/models/common/CustomType";
|
|
4
|
+
import { managerClient } from "@src/managerClient";
|
|
5
|
+
|
|
6
|
+
export async function getLegacySliceMachineState() {
|
|
7
|
+
const rawState = await managerClient.getState();
|
|
8
|
+
|
|
9
|
+
// `rawState` from the client contains non-SM-specific models. We need to
|
|
10
|
+
// transform the data to something SM recognizes.
|
|
11
|
+
const state: ServerState = {
|
|
12
|
+
...rawState,
|
|
13
|
+
libraries: rawState.libraries.map((library) => {
|
|
14
|
+
return {
|
|
15
|
+
...library,
|
|
16
|
+
components: library.components.map((component) => {
|
|
17
|
+
return {
|
|
18
|
+
...component,
|
|
19
|
+
model: Slices.toSM(component.model),
|
|
20
|
+
|
|
21
|
+
// Replace screnshot Blobs with URLs.
|
|
22
|
+
screenshots: Object.fromEntries(
|
|
23
|
+
Object.entries(component.screenshots).map(
|
|
24
|
+
([variationID, screenshot]) => {
|
|
25
|
+
return [
|
|
26
|
+
variationID,
|
|
27
|
+
{
|
|
28
|
+
...screenshot,
|
|
29
|
+
url: URL.createObjectURL(screenshot.data),
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
},
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
};
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
}),
|
|
39
|
+
customTypes: rawState.customTypes.map((customTypeModel) => {
|
|
40
|
+
return CustomTypes.toSM(customTypeModel);
|
|
41
|
+
}),
|
|
42
|
+
remoteCustomTypes: rawState.remoteCustomTypes.map(
|
|
43
|
+
(remoteCustomTypeModel) => {
|
|
44
|
+
return CustomTypes.toSM(remoteCustomTypeModel);
|
|
45
|
+
},
|
|
46
|
+
),
|
|
47
|
+
remoteSlices: rawState.remoteSlices.map((remoteSliceModel) => {
|
|
48
|
+
return Slices.toSM(remoteSliceModel);
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return state;
|
|
53
|
+
}
|
|
@@ -46,6 +46,7 @@ export const ConvertLegacySliceAsNewSliceDialog: FC<DialogProps> = ({
|
|
|
46
46
|
validateOnChange
|
|
47
47
|
validateOnMount
|
|
48
48
|
initialValues={{
|
|
49
|
+
_init: false,
|
|
49
50
|
from: libraries[0]?.name,
|
|
50
51
|
sliceName: pascalize(slice.key),
|
|
51
52
|
}}
|
|
@@ -59,7 +60,7 @@ export const ConvertLegacySliceAsNewSliceDialog: FC<DialogProps> = ({
|
|
|
59
60
|
{(formik) => {
|
|
60
61
|
return (
|
|
61
62
|
<form id="convert-legacy-slice-as-new-slice-dialog">
|
|
62
|
-
<Box flexDirection="column">
|
|
63
|
+
<Box display="flex" flexDirection="column">
|
|
63
64
|
<ScrollArea
|
|
64
65
|
className={styles.scrollArea}
|
|
65
66
|
style={{ width: 448 }}
|
|
@@ -74,7 +75,7 @@ export const ConvertLegacySliceAsNewSliceDialog: FC<DialogProps> = ({
|
|
|
74
75
|
This will not migrate your component. You will need to do
|
|
75
76
|
that manually.
|
|
76
77
|
</Text>
|
|
77
|
-
<Box flexDirection="column" gap={4}>
|
|
78
|
+
<Box display="flex" flexDirection="column" gap={4}>
|
|
78
79
|
<label className={styles.label}>
|
|
79
80
|
<Text variant="bold">Display name*</Text>
|
|
80
81
|
{typeof formik.errors.sliceName === "string" ? (
|
|
@@ -101,7 +102,7 @@ export const ConvertLegacySliceAsNewSliceDialog: FC<DialogProps> = ({
|
|
|
101
102
|
A display name for the slice
|
|
102
103
|
</Text>
|
|
103
104
|
</Box>
|
|
104
|
-
<Box flexDirection="column" gap={4}>
|
|
105
|
+
<Box display="flex" flexDirection="column" gap={4}>
|
|
105
106
|
<label className={styles.label}>
|
|
106
107
|
<Text variant="bold">Slice library*</Text>
|
|
107
108
|
{typeof formik.errors.from === "string" ? (
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
Icon,
|
|
10
10
|
IconButton,
|
|
11
11
|
Text,
|
|
12
|
-
Tooltip,
|
|
13
12
|
tokens,
|
|
14
13
|
} from "@prismicio/editor-ui";
|
|
15
14
|
import Link from "next/link";
|
|
@@ -53,12 +52,7 @@ type SharedSliceCardProps = {
|
|
|
53
52
|
);
|
|
54
53
|
|
|
55
54
|
type Action =
|
|
56
|
-
| {
|
|
57
|
-
type: "menu";
|
|
58
|
-
onRemove: () => void;
|
|
59
|
-
onRename: () => void;
|
|
60
|
-
removeDisabled?: boolean;
|
|
61
|
-
}
|
|
55
|
+
| { type: "menu"; onRemove?: () => void; onRename?: () => void }
|
|
62
56
|
| { type: "remove"; onRemove: () => void }
|
|
63
57
|
| ({ type: "status" } & Omit<StatusBadgeProps, "modelType">);
|
|
64
58
|
|
|
@@ -169,6 +163,14 @@ export const SharedSliceCard: FC<SharedSliceCardProps> = (props) => {
|
|
|
169
163
|
align="end"
|
|
170
164
|
data-cy="slice-action-icon-dropdown"
|
|
171
165
|
>
|
|
166
|
+
{action.onRename ? (
|
|
167
|
+
<DropdownMenuItem
|
|
168
|
+
onSelect={action.onRename}
|
|
169
|
+
startIcon={<Icon name="edit" />}
|
|
170
|
+
>
|
|
171
|
+
Rename
|
|
172
|
+
</DropdownMenuItem>
|
|
173
|
+
) : undefined}
|
|
172
174
|
{canUpdateScreenshot && disableOverlay ? (
|
|
173
175
|
<DropdownMenuItem
|
|
174
176
|
onSelect={onUpdateScreenshot}
|
|
@@ -177,29 +179,15 @@ export const SharedSliceCard: FC<SharedSliceCardProps> = (props) => {
|
|
|
177
179
|
Update screenshot
|
|
178
180
|
</DropdownMenuItem>
|
|
179
181
|
) : undefined}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
>
|
|
184
|
-
Rename
|
|
185
|
-
</DropdownMenuItem>
|
|
186
|
-
{action.removeDisabled === true && hasVariationId ? (
|
|
187
|
-
<Tooltip
|
|
188
|
-
content="The slice needs to have at least one variation."
|
|
189
|
-
side="bottom"
|
|
190
|
-
stableMount
|
|
191
|
-
>
|
|
192
|
-
<RemoveDropdownMenuItem
|
|
193
|
-
disabled
|
|
194
|
-
onSelect={action.onRemove}
|
|
195
|
-
/>
|
|
196
|
-
</Tooltip>
|
|
197
|
-
) : (
|
|
198
|
-
<RemoveDropdownMenuItem
|
|
199
|
-
disabled={action.removeDisabled === true}
|
|
182
|
+
{action.onRemove ? (
|
|
183
|
+
<DropdownMenuItem
|
|
184
|
+
color="tomato"
|
|
200
185
|
onSelect={action.onRemove}
|
|
201
|
-
|
|
202
|
-
|
|
186
|
+
startIcon={<Icon name="delete" />}
|
|
187
|
+
>
|
|
188
|
+
Delete
|
|
189
|
+
</DropdownMenuItem>
|
|
190
|
+
) : undefined}
|
|
203
191
|
</DropdownMenuContent>
|
|
204
192
|
</DropdownMenu>
|
|
205
193
|
) : action.type === "remove" ? (
|
|
@@ -255,18 +243,3 @@ const UpdateScreenshotButton: FC<UpdateScreenshotButtonProps> = (props) => (
|
|
|
255
243
|
Update screenshot
|
|
256
244
|
</Button>
|
|
257
245
|
);
|
|
258
|
-
|
|
259
|
-
type RemoveDropdownMenuItemProps = {
|
|
260
|
-
disabled: boolean;
|
|
261
|
-
onSelect: () => void;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
const RemoveDropdownMenuItem: FC<RemoveDropdownMenuItemProps> = (props) => (
|
|
265
|
-
<DropdownMenuItem
|
|
266
|
-
{...props}
|
|
267
|
-
color="tomato"
|
|
268
|
-
startIcon={<Icon name="delete" />}
|
|
269
|
-
>
|
|
270
|
-
Delete
|
|
271
|
-
</DropdownMenuItem>
|
|
272
|
-
);
|
|
@@ -15,7 +15,7 @@ import { SliceSM } from "@lib/models/common/Slice";
|
|
|
15
15
|
import { CustomTypeSM } from "@lib/models/common/CustomType";
|
|
16
16
|
import ErrorWithStatus from "@lib/models/common/ErrorWithStatus";
|
|
17
17
|
import { AuthStatus } from "../userContext/types";
|
|
18
|
-
import
|
|
18
|
+
import { getChangelogApiClient } from "@src/apiClient";
|
|
19
19
|
import { call, fork, put, takeLatest } from "redux-saga/effects";
|
|
20
20
|
import { withLoader } from "../loading";
|
|
21
21
|
import { LoadingKeysEnum } from "../loading/types";
|
|
@@ -142,7 +142,7 @@ export function* getChangelogSaga(): Generator<
|
|
|
142
142
|
PackageChangelog
|
|
143
143
|
> {
|
|
144
144
|
try {
|
|
145
|
-
const changelog = yield call(
|
|
145
|
+
const changelog = yield call(getChangelogApiClient);
|
|
146
146
|
yield put(getChangelogCreator.success({ changelog }));
|
|
147
147
|
} catch {
|
|
148
148
|
yield put(getChangelogCreator.failure());
|
|
@@ -9,7 +9,10 @@ import { getType } from "typesafe-actions";
|
|
|
9
9
|
import { withLoader } from "../loading";
|
|
10
10
|
import { LoadingKeysEnum } from "../loading/types";
|
|
11
11
|
import { generateSliceCustomScreenshotCreator } from "./actions";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
generateSliceCustomScreenshotApiClient,
|
|
14
|
+
telemetry,
|
|
15
|
+
} from "@src/apiClient";
|
|
13
16
|
import { openToasterCreator, ToasterType } from "@src/modules/toaster";
|
|
14
17
|
|
|
15
18
|
export function* generateSliceCustomScreenshotSaga({
|
|
@@ -22,12 +25,12 @@ export function* generateSliceCustomScreenshotSaga({
|
|
|
22
25
|
form.append("libraryName", component.from);
|
|
23
26
|
form.append("sliceName", component.model.name);
|
|
24
27
|
form.append("variationId", variationId);
|
|
25
|
-
const response = (yield call(
|
|
28
|
+
const response = (yield call(generateSliceCustomScreenshotApiClient, {
|
|
26
29
|
libraryName: component.from,
|
|
27
30
|
sliceId: component.model.id,
|
|
28
31
|
variationId,
|
|
29
32
|
file,
|
|
30
|
-
})) as SagaReturnType<typeof
|
|
33
|
+
})) as SagaReturnType<typeof generateSliceCustomScreenshotApiClient>;
|
|
31
34
|
|
|
32
35
|
if (!response?.url) {
|
|
33
36
|
throw Error("No screenshot saved");
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ActionType, createAction, createAsyncAction } from "typesafe-actions";
|
|
2
2
|
import { NestableWidget } from "@prismicio/types-internal/lib/customtypes";
|
|
3
|
-
import type { SliceBuilderState } from "@builders/SliceBuilder";
|
|
4
3
|
import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
5
4
|
import { renameSliceCreator } from "../slices";
|
|
6
5
|
import { SelectedSliceStoreType } from "./types";
|
|
@@ -18,7 +17,6 @@ export type SelectedSliceActions =
|
|
|
18
17
|
| ActionType<typeof updateSliceWidgetMockCreator>
|
|
19
18
|
| ActionType<typeof deleteSliceWidgetMockCreator>
|
|
20
19
|
| ActionType<typeof updateSliceCreator>
|
|
21
|
-
| ActionType<typeof updateAndSaveSliceCreator>
|
|
22
20
|
| ActionType<typeof copyVariationSliceCreator>
|
|
23
21
|
| ActionType<typeof renameSliceCreator>
|
|
24
22
|
| ActionType<typeof refreshStateCreator>
|
|
@@ -88,17 +86,14 @@ export const updateSliceCreator = createAsyncAction(
|
|
|
88
86
|
)<
|
|
89
87
|
{
|
|
90
88
|
component: ComponentUI;
|
|
91
|
-
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
+
setData: (data: any) => void;
|
|
92
91
|
},
|
|
93
92
|
{
|
|
94
93
|
component: ComponentUI;
|
|
95
94
|
}
|
|
96
95
|
>();
|
|
97
96
|
|
|
98
|
-
export const updateAndSaveSliceCreator = createAction("SLICE/UPDATE_AND_SAVE")<{
|
|
99
|
-
component: ComponentUI;
|
|
100
|
-
}>();
|
|
101
|
-
|
|
102
97
|
export const copyVariationSliceCreator = createAction("SLICE/COPY_VARIATION")<{
|
|
103
98
|
key: string;
|
|
104
99
|
name: string;
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
copyVariationSliceCreator,
|
|
7
7
|
initSliceStoreCreator,
|
|
8
8
|
removeSliceWidgetCreator,
|
|
9
|
-
updateAndSaveSliceCreator,
|
|
10
9
|
reorderSliceWidgetCreator,
|
|
11
10
|
replaceSliceWidgetCreator,
|
|
12
11
|
SelectedSliceActions,
|
|
@@ -156,11 +155,7 @@ export const selectedSliceReducer: Reducer<
|
|
|
156
155
|
model: renamedSlice,
|
|
157
156
|
};
|
|
158
157
|
}
|
|
159
|
-
|
|
160
|
-
return prevState
|
|
161
|
-
? { ...prevState, ...action.payload.component }
|
|
162
|
-
: prevState;
|
|
163
|
-
}
|
|
158
|
+
|
|
164
159
|
case getType(updateSelectedSliceMocks): {
|
|
165
160
|
if (!prevState) return prevState;
|
|
166
161
|
const { mocks } = action.payload;
|
|
@@ -10,32 +10,40 @@ import { getType } from "typesafe-actions";
|
|
|
10
10
|
import { withLoader } from "../loading";
|
|
11
11
|
import { LoadingKeysEnum } from "../loading/types";
|
|
12
12
|
import { updateSliceCreator } from "./actions";
|
|
13
|
-
import { readSliceMocks,
|
|
13
|
+
import { readSliceMocks, updateSliceApiClient } from "@src/apiClient";
|
|
14
14
|
import { openToasterCreator, ToasterType } from "@src/modules/toaster";
|
|
15
15
|
import { SliceToastMessage } from "@components/ToasterContainer";
|
|
16
16
|
|
|
17
17
|
export function* updateSliceSaga({
|
|
18
18
|
payload,
|
|
19
19
|
}: ReturnType<typeof updateSliceCreator.request>) {
|
|
20
|
-
const { component,
|
|
20
|
+
const { component, setData } = payload;
|
|
21
21
|
|
|
22
22
|
try {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
setData({
|
|
24
|
+
loading: true,
|
|
25
|
+
done: false,
|
|
26
|
+
error: null,
|
|
27
|
+
status: null,
|
|
28
|
+
message: null,
|
|
29
|
+
});
|
|
30
|
+
const { errors } = (yield call(
|
|
31
|
+
updateSliceApiClient,
|
|
32
|
+
component,
|
|
33
|
+
)) as SagaReturnType<typeof updateSliceApiClient>;
|
|
27
34
|
if (errors.length > 0) {
|
|
28
|
-
return
|
|
35
|
+
return setData({
|
|
29
36
|
loading: false,
|
|
30
37
|
done: true,
|
|
31
|
-
error:
|
|
38
|
+
error: errors,
|
|
32
39
|
message: errors[0].message,
|
|
40
|
+
status: 500,
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
|
-
|
|
43
|
+
setData({
|
|
36
44
|
loading: false,
|
|
37
45
|
done: true,
|
|
38
|
-
error:
|
|
46
|
+
error: null,
|
|
39
47
|
message: SliceToastMessage({
|
|
40
48
|
path: `${component.from}/${component.model.name}/model.json`,
|
|
41
49
|
}),
|
|
@@ -25,10 +25,7 @@ import { modalCloseCreator } from "@src/modules/modal";
|
|
|
25
25
|
import { refreshStateCreator } from "@src/modules/environment";
|
|
26
26
|
import { SliceMachineStoreType } from "@src/redux/type";
|
|
27
27
|
import { openToasterCreator, ToasterType } from "@src/modules/toaster";
|
|
28
|
-
import {
|
|
29
|
-
updateAndSaveSliceCreator,
|
|
30
|
-
updateSliceCreator,
|
|
31
|
-
} from "../selectedSlice/actions";
|
|
28
|
+
import { updateSliceCreator } from "../selectedSlice/actions";
|
|
32
29
|
import { generateSliceCustomScreenshotCreator } from "../screenshots/actions";
|
|
33
30
|
import { selectSliceById } from "../selectedSlice/selectors";
|
|
34
31
|
import { SlicesStoreType } from "./types";
|
|
@@ -79,7 +76,6 @@ type SlicesActions =
|
|
|
79
76
|
| ActionType<typeof renameSliceCreator>
|
|
80
77
|
| ActionType<typeof deleteSliceCreator>
|
|
81
78
|
| ActionType<typeof updateSliceCreator>
|
|
82
|
-
| ActionType<typeof updateAndSaveSliceCreator>
|
|
83
79
|
| ActionType<typeof generateSliceCustomScreenshotCreator>
|
|
84
80
|
| ActionType<typeof updateSliceMock>;
|
|
85
81
|
|
|
@@ -161,24 +157,6 @@ export const slicesReducer: Reducer<SlicesStoreType | null, SlicesActions> = (
|
|
|
161
157
|
|
|
162
158
|
return { ...state, libraries: newLibraries };
|
|
163
159
|
}
|
|
164
|
-
case getType(updateAndSaveSliceCreator): {
|
|
165
|
-
const { component: newComponent } = action.payload;
|
|
166
|
-
return {
|
|
167
|
-
...state,
|
|
168
|
-
libraries: state.libraries.map((library) =>
|
|
169
|
-
library.name === newComponent.from
|
|
170
|
-
? {
|
|
171
|
-
...library,
|
|
172
|
-
components: library.components.map((component) =>
|
|
173
|
-
component.model.id === newComponent.model.id
|
|
174
|
-
? newComponent
|
|
175
|
-
: component,
|
|
176
|
-
),
|
|
177
|
-
}
|
|
178
|
-
: library,
|
|
179
|
-
),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
160
|
case getType(generateSliceCustomScreenshotCreator.success): {
|
|
183
161
|
const { component, screenshot, variationId } = action.payload;
|
|
184
162
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
1
|
import { ToasterType } from "../toaster";
|
|
4
2
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export interface ToastPayload {
|
|
4
|
+
loading: boolean;
|
|
5
|
+
done: boolean;
|
|
6
|
+
warning: boolean;
|
|
7
|
+
message: string;
|
|
8
|
+
status: number;
|
|
9
|
+
error: Error | null;
|
|
10
|
+
}
|
|
8
11
|
|
|
9
12
|
export const handleRemoteResponse =
|
|
10
|
-
(addToast: (message:
|
|
13
|
+
(addToast: (message: string, type: ToasterType) => void) =>
|
|
11
14
|
(payload: ToastPayload) => {
|
|
12
15
|
if (payload.done) {
|
|
13
16
|
addToast(
|
|
@@ -16,6 +19,9 @@ export const handleRemoteResponse =
|
|
|
16
19
|
if (payload.error) {
|
|
17
20
|
return ToasterType.ERROR;
|
|
18
21
|
}
|
|
22
|
+
if (payload.warning) {
|
|
23
|
+
return ToasterType.WARNING;
|
|
24
|
+
}
|
|
19
25
|
return ToasterType.SUCCESS;
|
|
20
26
|
})(),
|
|
21
27
|
);
|
|
@@ -45,7 +45,6 @@ import {
|
|
|
45
45
|
cleanupCustomTypeStoreCreator,
|
|
46
46
|
renameSelectedCustomTypeLabel,
|
|
47
47
|
} from "./selectedCustomType";
|
|
48
|
-
import type { SliceBuilderState } from "@builders/SliceBuilder";
|
|
49
48
|
import {
|
|
50
49
|
CustomTypeSM,
|
|
51
50
|
CustomTypes,
|
|
@@ -63,7 +62,6 @@ import {
|
|
|
63
62
|
removeSliceWidgetCreator,
|
|
64
63
|
reorderSliceWidgetCreator,
|
|
65
64
|
replaceSliceWidgetCreator,
|
|
66
|
-
updateAndSaveSliceCreator,
|
|
67
65
|
updateSliceCreator,
|
|
68
66
|
updateSliceWidgetMockCreator,
|
|
69
67
|
} from "./selectedSlice/actions";
|
|
@@ -379,20 +377,17 @@ const useSliceMachineActions = () => {
|
|
|
379
377
|
|
|
380
378
|
const updateSlice = (
|
|
381
379
|
component: ComponentUI,
|
|
382
|
-
|
|
380
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
381
|
+
setData: (data: any) => void,
|
|
383
382
|
) => {
|
|
384
383
|
dispatch(
|
|
385
384
|
updateSliceCreator.request({
|
|
386
385
|
component,
|
|
387
|
-
|
|
386
|
+
setData,
|
|
388
387
|
}),
|
|
389
388
|
);
|
|
390
389
|
};
|
|
391
390
|
|
|
392
|
-
const updateAndSaveSlice = (component: ComponentUI) => {
|
|
393
|
-
dispatch(updateAndSaveSliceCreator({ component }));
|
|
394
|
-
};
|
|
395
|
-
|
|
396
391
|
const copyVariationSlice = (
|
|
397
392
|
key: string,
|
|
398
393
|
name: string,
|
|
@@ -502,7 +497,6 @@ const useSliceMachineActions = () => {
|
|
|
502
497
|
deleteSliceWidgetMock,
|
|
503
498
|
generateSliceCustomScreenshot,
|
|
504
499
|
updateSlice,
|
|
505
|
-
updateAndSaveSlice,
|
|
506
500
|
copyVariationSlice,
|
|
507
501
|
createSliceSuccess,
|
|
508
502
|
renameSlice,
|
|
@@ -167,18 +167,14 @@ describe("slices", () => {
|
|
|
167
167
|
},
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
-
const createOneButton =
|
|
170
|
+
const createOneButton = await screen.findByTestId("create-slice");
|
|
171
171
|
await act(async () => {
|
|
172
|
-
|
|
173
|
-
fireEvent.click(createOneButton);
|
|
174
|
-
}
|
|
172
|
+
fireEvent.click(createOneButton);
|
|
175
173
|
});
|
|
176
174
|
|
|
177
|
-
const nameInput =
|
|
175
|
+
const nameInput = await screen.findByPlaceholderText(/slice api id/i);
|
|
178
176
|
await act(async () => {
|
|
179
|
-
|
|
180
|
-
fireEvent.change(nameInput, { target: { value: "FooBar" } });
|
|
181
|
-
}
|
|
177
|
+
fireEvent.change(nameInput, { target: { value: "FooBar" } });
|
|
182
178
|
});
|
|
183
179
|
|
|
184
180
|
const createSliceModal = screen.getByLabelText("Create a new slice");
|
|
@@ -36,6 +36,8 @@ export const dummyServerState: Pick<
|
|
|
36
36
|
"https://0yyeb2g040.execute-api.us-east-1.amazonaws.com/prod/",
|
|
37
37
|
PrismicOembed: "https://oembed.prismic.io",
|
|
38
38
|
PrismicUnsplash: "https://unsplash.prismic.io",
|
|
39
|
+
SliceMachineV1:
|
|
40
|
+
"https://21vvgrh0s6.execute-api.us-east-1.amazonaws.com/v1/",
|
|
39
41
|
},
|
|
40
42
|
shortId: "shortId",
|
|
41
43
|
supportsSliceSimulator: true,
|
|
@@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
2
2
|
import { testSaga } from "redux-saga-test-plan";
|
|
3
3
|
import { updateSliceSaga } from "@src/modules/selectedSlice/sagas";
|
|
4
4
|
import { updateSliceCreator } from "@src/modules/selectedSlice/actions";
|
|
5
|
-
import { readSliceMocks,
|
|
5
|
+
import { readSliceMocks, updateSliceApiClient } from "@src/apiClient";
|
|
6
6
|
import { openToasterCreator, ToasterType } from "@src/modules/toaster";
|
|
7
7
|
import { getSelectedSliceDummyData } from "./__testutils__/getSelectedSliceDummyData";
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ const { dummySliceState } = getSelectedSliceDummyData();
|
|
|
11
11
|
describe("[Selected Slice sagas]", () => {
|
|
12
12
|
describe("[updateSliceSaga]", () => {
|
|
13
13
|
it("should call the api and dispatch the success action", () => {
|
|
14
|
-
const
|
|
14
|
+
const mockSetData = vi.fn<
|
|
15
15
|
{
|
|
16
16
|
error: boolean;
|
|
17
17
|
done: boolean;
|
|
@@ -28,12 +28,11 @@ describe("[Selected Slice sagas]", () => {
|
|
|
28
28
|
updateSliceSaga,
|
|
29
29
|
updateSliceCreator.request({
|
|
30
30
|
component: dummySliceState,
|
|
31
|
-
|
|
32
|
-
setSliceBuilderState: mockSetSliceBuilderState,
|
|
31
|
+
setData: mockSetData,
|
|
33
32
|
}),
|
|
34
33
|
);
|
|
35
34
|
|
|
36
|
-
saga.next().call(
|
|
35
|
+
saga.next().call(updateSliceApiClient, dummySliceState);
|
|
37
36
|
|
|
38
37
|
saga.next({ errors: [] }).call(readSliceMocks, {
|
|
39
38
|
libraryID: dummySliceState.from,
|
|
@@ -48,25 +47,24 @@ describe("[Selected Slice sagas]", () => {
|
|
|
48
47
|
|
|
49
48
|
saga.next().isDone();
|
|
50
49
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
expect(
|
|
54
|
-
expect(
|
|
55
|
-
expect(
|
|
56
|
-
expect(mockSetSliceBuilderStateCalls?.message.props.message).toBe(
|
|
50
|
+
const mockSetDataCalls = mockSetData.mock.lastCall?.[0];
|
|
51
|
+
expect(mockSetDataCalls?.error).toBe(null);
|
|
52
|
+
expect(mockSetDataCalls?.done).toBe(true);
|
|
53
|
+
expect(mockSetDataCalls?.loading).toBe(false);
|
|
54
|
+
expect(mockSetDataCalls?.message.props.message).toBe(
|
|
57
55
|
"Slice saved successfully at ",
|
|
58
56
|
);
|
|
59
|
-
expect(
|
|
57
|
+
expect(mockSetDataCalls?.message.props.path).toBe(
|
|
60
58
|
"slices/libName/DummySlice/model.json",
|
|
61
59
|
);
|
|
62
60
|
});
|
|
63
61
|
it("should open a error toaster on internal error", () => {
|
|
64
|
-
const
|
|
62
|
+
const mockSetData = vi.fn();
|
|
65
63
|
const saga = testSaga(
|
|
66
64
|
updateSliceSaga,
|
|
67
65
|
updateSliceCreator.request({
|
|
68
66
|
component: dummySliceState,
|
|
69
|
-
|
|
67
|
+
setData: mockSetData,
|
|
70
68
|
}),
|
|
71
69
|
).next();
|
|
72
70
|
|
|
@@ -12,9 +12,12 @@ describe("[Toaster utils]", () => {
|
|
|
12
12
|
it("should call addToast function on an success", () => {
|
|
13
13
|
const addToastFakeFunction = vi.fn();
|
|
14
14
|
const toastPayload: ToastPayload = {
|
|
15
|
+
loading: false,
|
|
15
16
|
done: true,
|
|
17
|
+
warning: false,
|
|
16
18
|
message: "message",
|
|
17
|
-
|
|
19
|
+
status: 200,
|
|
20
|
+
error: null,
|
|
18
21
|
};
|
|
19
22
|
handleRemoteResponse(addToastFakeFunction)(toastPayload);
|
|
20
23
|
|
|
@@ -26,18 +29,46 @@ describe("[Toaster utils]", () => {
|
|
|
26
29
|
|
|
27
30
|
it("shouldn't call addToast function on an unfinished request", () => {
|
|
28
31
|
const addToastFakeFunction = vi.fn();
|
|
29
|
-
const toastPayload: ToastPayload = {
|
|
32
|
+
const toastPayload: ToastPayload = {
|
|
33
|
+
loading: false,
|
|
34
|
+
done: false,
|
|
35
|
+
warning: false,
|
|
36
|
+
message: "message",
|
|
37
|
+
status: 200,
|
|
38
|
+
error: null,
|
|
39
|
+
};
|
|
30
40
|
handleRemoteResponse(addToastFakeFunction)(toastPayload);
|
|
31
41
|
|
|
32
42
|
expect(addToastFakeFunction).toHaveBeenCalledTimes(0);
|
|
33
43
|
});
|
|
34
44
|
|
|
45
|
+
it("shouldn't call addToast function on request with warnings", () => {
|
|
46
|
+
const addToastFakeFunction = vi.fn();
|
|
47
|
+
const toastPayload: ToastPayload = {
|
|
48
|
+
loading: false,
|
|
49
|
+
done: true,
|
|
50
|
+
warning: true,
|
|
51
|
+
message: "message",
|
|
52
|
+
status: 200,
|
|
53
|
+
error: null,
|
|
54
|
+
};
|
|
55
|
+
handleRemoteResponse(addToastFakeFunction)(toastPayload);
|
|
56
|
+
|
|
57
|
+
expect(addToastFakeFunction).toHaveBeenCalledWith(
|
|
58
|
+
"message",
|
|
59
|
+
ToasterType.WARNING,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
35
63
|
it("shouldn't call addToast function on a request with errors", () => {
|
|
36
64
|
const addToastFakeFunction = vi.fn();
|
|
37
65
|
const toastPayload: ToastPayload = {
|
|
66
|
+
loading: false,
|
|
38
67
|
done: true,
|
|
68
|
+
warning: true,
|
|
39
69
|
message: "message",
|
|
40
|
-
|
|
70
|
+
status: 200,
|
|
71
|
+
error: new Error(),
|
|
41
72
|
};
|
|
42
73
|
handleRemoteResponse(addToastFakeFunction)(toastPayload);
|
|
43
74
|
|