slice-machine-ui 1.23.2-beta.3 → 1.23.2-beta.5
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/DeleteSliceModal/index.tsx +34 -24
- package/components/Forms/CreateCustomTypeModal/CreateCustomTypeModal.tsx +61 -38
- package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +2 -2
- package/components/Forms/RenameSliceModal/RenameSliceModal.tsx +33 -21
- package/components/Navigation/ChangesListItem.tsx +14 -32
- package/out/404.html +1 -1
- package/out/_next/static/W3x14bv5_NtxtSjAB0JUM/_buildManifest.js +1 -0
- package/out/_next/static/chunks/{183-aab7066c73ebde44.js → 183-4feb6bb3eddbc768.js} +1 -1
- package/out/_next/static/chunks/25-01f422cea8066349.js +1 -0
- package/out/_next/static/chunks/{318-2112803ca34b2f49.js → 318-34a2dea7cfd4661d.js} +1 -1
- package/out/_next/static/chunks/727-358d7fae68a880b3.js +1 -0
- package/out/_next/static/chunks/799-d95a93e965557aeb.js +1 -0
- package/out/_next/static/chunks/904-1ff7519adece2b55.js +1 -0
- package/out/_next/static/chunks/pages/{_app-9f3513533bb2dfb8.js → _app-a2fa2db79a1e9a1e.js} +37 -37
- package/out/_next/static/chunks/pages/{changes-2a976f9efeb719aa.js → changes-92c84f6cac0285fd.js} +1 -1
- package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-3f862ad6111a1fc0.js → [customTypeId]-97ab3b90b85d645d.js} +1 -1
- package/out/_next/static/chunks/pages/{custom-types-94b8f8dbf7727412.js → custom-types-3c8e721ec6802127.js} +1 -1
- package/out/_next/static/chunks/pages/index-cf93d16e9c63b6db.js +1 -0
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-d1ffca11c42f2603.js → [pageTypeId]-84a22c5e480d3fa9.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/{simulator-897ca93c114a1435.js → simulator-52c3e1f9d14160b8.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-608d206d10a719e3.js +1 -0
- package/out/_next/static/chunks/pages/slices-b0b58192a87df822.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 +3 -3
- package/pages/slices.tsx +20 -8
- package/src/apiClient.ts +1 -22
- package/src/domain/__tests__/customType.test.ts +179 -0
- package/src/domain/customType.ts +110 -2
- package/src/domain/slice.ts +38 -0
- package/src/features/customTypes/PageTypeOnboarding.tsx +21 -26
- package/src/features/customTypes/actions/convertCustomToPageType.ts +14 -10
- package/src/features/customTypes/actions/createCustomType.ts +69 -0
- package/src/features/customTypes/actions/deleteCustomType.ts +13 -3
- package/src/features/customTypes/actions/renameCustomType.ts +10 -4
- package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +3 -1
- package/src/features/customTypes/customTypesTable/CustomTypesTable.tsx +8 -8
- package/src/features/customTypes/customTypesTable/CustomTypesTablePage.tsx +18 -17
- package/src/features/slices/actions/createSlice.ts +5 -29
- package/src/features/slices/actions/deleteSlice.ts +33 -0
- package/src/features/slices/actions/renameSlice.ts +37 -0
- package/src/modules/availableCustomTypes/index.ts +29 -135
- package/src/modules/loading/types.ts +0 -5
- package/src/modules/modal/types.ts +0 -3
- package/src/modules/slices/index.ts +27 -193
- package/src/modules/slices/selector.ts +0 -14
- package/src/modules/useSliceMachineActions.ts +70 -89
- package/src/modules/userContext/index.ts +3 -3
- package/src/redux/saga.ts +0 -4
- package/test/src/modules/availableCustomTypes/index.test.ts +2 -243
- package/test/src/modules/slices.test.ts +1 -267
- package/out/_next/static/RRBm5bm2F__Ws0vsvXhN6/_buildManifest.js +0 -1
- package/out/_next/static/chunks/25-37d6fa7f064be04b.js +0 -1
- package/out/_next/static/chunks/727-3a3bc32518778317.js +0 -1
- package/out/_next/static/chunks/731-501990ebe6a71b32.js +0 -1
- package/out/_next/static/chunks/904-9a4c1264727ae89a.js +0 -1
- package/out/_next/static/chunks/pages/index-64cfb8b0948ba8ef.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-b2a9d773ce5d7739.js +0 -1
- package/out/_next/static/chunks/pages/slices-e9c70c082ca3e3f9.js +0 -1
- package/src/features/customTypes/__tests__/createCustomType.test.ts +0 -159
- package/src/features/customTypes/customTypesTable/createCustomType.ts +0 -107
- package/test/components/CreateCustomTypeModal.test.tsx +0 -73
- /package/out/_next/static/{RRBm5bm2F__Ws0vsvXhN6 → W3x14bv5_NtxtSjAB0JUM}/_ssgManifest.js +0 -0
|
@@ -9,17 +9,20 @@ import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
|
9
9
|
|
|
10
10
|
export async function convertCustomToPageType(
|
|
11
11
|
customType: CustomType,
|
|
12
|
-
|
|
12
|
+
onSuccess: (newCustomType: CustomType) => void,
|
|
13
13
|
) {
|
|
14
14
|
const customTypesMessages =
|
|
15
15
|
CUSTOM_TYPES_MESSAGES[customType.format as CustomTypeFormat];
|
|
16
16
|
|
|
17
17
|
try {
|
|
18
18
|
const newCustomType = convertToPageType(customType);
|
|
19
|
-
await updateCustomType(newCustomType);
|
|
19
|
+
const { errors } = await updateCustomType(newCustomType);
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
if (errors.length > 0) {
|
|
22
|
+
throw errors;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onSuccess(newCustomType);
|
|
23
26
|
|
|
24
27
|
toast.success(
|
|
25
28
|
`${customTypesMessages.name({
|
|
@@ -28,11 +31,12 @@ export async function convertCustomToPageType(
|
|
|
28
31
|
})} converted to page type`,
|
|
29
32
|
);
|
|
30
33
|
} catch (e) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
34
|
+
const errorMessage = `Internal Error: ${customTypesMessages.name({
|
|
35
|
+
start: true,
|
|
36
|
+
plural: false,
|
|
37
|
+
})} not converted to page type`;
|
|
38
|
+
|
|
39
|
+
console.error(errorMessage, e);
|
|
40
|
+
toast.error(errorMessage);
|
|
37
41
|
}
|
|
38
42
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { toast } from "react-toastify";
|
|
2
|
+
import { CustomType } from "@prismicio/types-internal/lib/customtypes";
|
|
3
|
+
|
|
4
|
+
import { ToastMessageWithPath } from "@components/ToasterContainer";
|
|
5
|
+
import { CustomTypeFormat } from "@slicemachine/manager";
|
|
6
|
+
import { telemetry, updateCustomType } from "@src/apiClient";
|
|
7
|
+
import { create } from "@src/domain/customType";
|
|
8
|
+
|
|
9
|
+
import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
10
|
+
|
|
11
|
+
type DeleteCustomTypeArgs = {
|
|
12
|
+
format: CustomTypeFormat;
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
origin: CustomTypeOrigin;
|
|
16
|
+
repeatable: boolean;
|
|
17
|
+
onSuccess: (newCustomType: CustomType) => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type CustomTypeOrigin = "onboarding" | "table";
|
|
21
|
+
|
|
22
|
+
export async function createCustomType(args: DeleteCustomTypeArgs) {
|
|
23
|
+
const { id, label, repeatable, format, onSuccess } = args;
|
|
24
|
+
const customTypesMessages = CUSTOM_TYPES_MESSAGES[format];
|
|
25
|
+
|
|
26
|
+
const newCustomType: CustomType = create({
|
|
27
|
+
id,
|
|
28
|
+
label,
|
|
29
|
+
repeatable,
|
|
30
|
+
format,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const { errors } = await updateCustomType(newCustomType);
|
|
35
|
+
|
|
36
|
+
if (errors.length > 0) {
|
|
37
|
+
throw errors;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void telemetry.track({
|
|
41
|
+
event: "custom-type:created",
|
|
42
|
+
id: newCustomType.id,
|
|
43
|
+
name: label,
|
|
44
|
+
format: format,
|
|
45
|
+
type: repeatable ? "repeatable" : "single",
|
|
46
|
+
origin: "table",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await onSuccess(newCustomType);
|
|
50
|
+
|
|
51
|
+
toast.success(
|
|
52
|
+
ToastMessageWithPath({
|
|
53
|
+
message: `${customTypesMessages.name({
|
|
54
|
+
start: true,
|
|
55
|
+
plural: false,
|
|
56
|
+
})} saved successfully at `,
|
|
57
|
+
path: `./customtypes/${newCustomType.id}/index.json`,
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
const errorMessage = `Internal Error: ${customTypesMessages.name({
|
|
62
|
+
start: true,
|
|
63
|
+
plural: false,
|
|
64
|
+
})} not saved`;
|
|
65
|
+
|
|
66
|
+
console.error(errorMessage, e);
|
|
67
|
+
toast.error(errorMessage);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { toast } from "react-toastify";
|
|
1
2
|
import { CustomType } from "@prismicio/types-internal/lib/customtypes";
|
|
3
|
+
|
|
2
4
|
import { managerClient } from "@src/managerClient";
|
|
5
|
+
import { CustomTypeFormat } from "@slicemachine/manager";
|
|
6
|
+
|
|
3
7
|
import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
4
|
-
import { CustomTypeFormat } from "@slicemachine/manager/*";
|
|
5
|
-
import { toast } from "react-toastify";
|
|
6
8
|
|
|
7
9
|
type DeleteCustomTypeArgs = {
|
|
8
10
|
customType: CustomType;
|
|
@@ -17,7 +19,13 @@ export async function deleteCustomType({
|
|
|
17
19
|
CUSTOM_TYPES_MESSAGES[customType.format as CustomTypeFormat];
|
|
18
20
|
|
|
19
21
|
try {
|
|
20
|
-
await managerClient.customTypes.deleteCustomType({
|
|
22
|
+
const { errors } = await managerClient.customTypes.deleteCustomType({
|
|
23
|
+
id: customType.id,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (errors.length > 0) {
|
|
27
|
+
throw errors;
|
|
28
|
+
}
|
|
21
29
|
|
|
22
30
|
onSuccess();
|
|
23
31
|
|
|
@@ -32,6 +40,8 @@ export async function deleteCustomType({
|
|
|
32
40
|
start: true,
|
|
33
41
|
plural: false,
|
|
34
42
|
})} could not be deleted`;
|
|
43
|
+
|
|
35
44
|
console.error(errorMessage, e);
|
|
45
|
+
toast.error(errorMessage);
|
|
36
46
|
}
|
|
37
47
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { toast } from "react-toastify";
|
|
1
2
|
import { CustomType } from "@prismicio/types-internal/lib/customtypes";
|
|
3
|
+
|
|
2
4
|
import { managerClient } from "@src/managerClient";
|
|
3
|
-
import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
4
5
|
import { CustomTypeFormat } from "@slicemachine/manager";
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
6
8
|
|
|
7
9
|
type RenameCustomTypeArgs = {
|
|
8
10
|
model: CustomType;
|
|
@@ -23,10 +25,14 @@ export async function renameCustomType({
|
|
|
23
25
|
label: newLabel,
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
await managerClient.customTypes.renameCustomType({
|
|
28
|
+
const { errors } = await managerClient.customTypes.renameCustomType({
|
|
27
29
|
model: renamedCustomType,
|
|
28
30
|
});
|
|
29
31
|
|
|
32
|
+
if (errors.length > 0) {
|
|
33
|
+
throw errors;
|
|
34
|
+
}
|
|
35
|
+
|
|
30
36
|
onSuccess(renamedCustomType);
|
|
31
37
|
|
|
32
38
|
toast.success(
|
|
@@ -40,8 +46,8 @@ export async function renameCustomType({
|
|
|
40
46
|
start: true,
|
|
41
47
|
plural: false,
|
|
42
48
|
})} could not be renamed`;
|
|
43
|
-
console.error(errorMessage, e);
|
|
44
49
|
|
|
50
|
+
console.error(errorMessage, e);
|
|
45
51
|
toast.error(errorMessage);
|
|
46
52
|
}
|
|
47
53
|
}
|
|
@@ -39,7 +39,9 @@ export const CustomTypesBuilderPage: FC = () => {
|
|
|
39
39
|
);
|
|
40
40
|
|
|
41
41
|
useEffect(() => {
|
|
42
|
-
//
|
|
42
|
+
// This is a fallback in case the user try to directly access a custom type
|
|
43
|
+
// that don't exist
|
|
44
|
+
// TODO(DT-1801): Implement a 404 page
|
|
43
45
|
if (!selectedCustomType || !hasLocal(selectedCustomType)) {
|
|
44
46
|
void router.replace("/");
|
|
45
47
|
}
|
|
@@ -11,16 +11,9 @@ import {
|
|
|
11
11
|
} from "@src/components/Table";
|
|
12
12
|
import { ReusableIcon } from "@src/icons/ReusableIcon";
|
|
13
13
|
import { UniqueIcon } from "@src/icons/UniqueIcon";
|
|
14
|
-
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
15
14
|
import { type CustomType } from "@prismicio/types-internal/lib/customtypes";
|
|
16
15
|
import { type CustomTypeFormat } from "@slicemachine/manager";
|
|
17
16
|
import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
|
|
18
|
-
import { CUSTOM_TYPES_CONFIG } from "../customTypesConfig";
|
|
19
|
-
import {
|
|
20
|
-
useCustomTypes,
|
|
21
|
-
useCustomTypesAutoRevalidation,
|
|
22
|
-
} from "./useCustomTypes";
|
|
23
|
-
|
|
24
17
|
import {
|
|
25
18
|
BlankSlate,
|
|
26
19
|
BlankSlateImage,
|
|
@@ -29,18 +22,25 @@ import {
|
|
|
29
22
|
BlankSlateActions,
|
|
30
23
|
BlankSlateContent,
|
|
31
24
|
} from "@src/components/BlankSlate";
|
|
25
|
+
|
|
26
|
+
import { CUSTOM_TYPES_CONFIG } from "../customTypesConfig";
|
|
32
27
|
import { EditDropdown } from "../EditDropdown";
|
|
28
|
+
import {
|
|
29
|
+
useCustomTypes,
|
|
30
|
+
useCustomTypesAutoRevalidation,
|
|
31
|
+
} from "./useCustomTypes";
|
|
33
32
|
|
|
34
33
|
type CustomTypesTableProps = {
|
|
35
34
|
format: CustomTypeFormat;
|
|
36
35
|
isCreatingCustomType: boolean;
|
|
36
|
+
openCreateCustomTypeModal: () => void;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
export const CustomTypesTable: FC<CustomTypesTableProps> = ({
|
|
40
40
|
format,
|
|
41
41
|
isCreatingCustomType,
|
|
42
|
+
openCreateCustomTypeModal,
|
|
42
43
|
}) => {
|
|
43
|
-
const { openCreateCustomTypeModal } = useSliceMachineActions();
|
|
44
44
|
const router = useRouter();
|
|
45
45
|
const { customTypes, updateCustomTypes } = useCustomTypes(format);
|
|
46
46
|
const sortedCustomTypes = customTypes.sort(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FC, Suspense } from "react";
|
|
1
|
+
import { type FC, Suspense, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
4
|
ErrorBoundary,
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
DefaultErrorMessage,
|
|
8
8
|
} from "@prismicio/editor-ui";
|
|
9
9
|
import Head from "next/head";
|
|
10
|
-
import { useSelector } from "react-redux";
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
12
|
AppLayout,
|
|
@@ -16,13 +15,10 @@ import {
|
|
|
16
15
|
AppLayoutContent,
|
|
17
16
|
AppLayoutHeader,
|
|
18
17
|
} from "@components/AppLayout";
|
|
19
|
-
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
20
|
-
import { isLoading } from "@src/modules/loading";
|
|
21
|
-
import { type SliceMachineStoreType } from "@src/redux/type";
|
|
22
|
-
import { LoadingKeysEnum } from "@src/modules/loading/types";
|
|
23
18
|
import { CreateCustomTypeModal } from "@components/Forms/CreateCustomTypeModal";
|
|
24
19
|
import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
|
|
25
20
|
import type { CustomTypeFormat } from "@slicemachine/manager";
|
|
21
|
+
|
|
26
22
|
import { CustomTypesTable } from "./CustomTypesTable";
|
|
27
23
|
|
|
28
24
|
type CustomTypesTablePageProps = {
|
|
@@ -33,15 +29,9 @@ export const CustomTypesTablePage: FC<CustomTypesTablePageProps> = ({
|
|
|
33
29
|
format,
|
|
34
30
|
}) => {
|
|
35
31
|
const customTypesMessages = CUSTOM_TYPES_MESSAGES[format];
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
(
|
|
39
|
-
isCreatingCustomType: isLoading(
|
|
40
|
-
store,
|
|
41
|
-
LoadingKeysEnum.CREATE_CUSTOM_TYPE,
|
|
42
|
-
),
|
|
43
|
-
}),
|
|
44
|
-
);
|
|
32
|
+
const [isCreatingCustomType, setIsCreatingCustomType] = useState(false);
|
|
33
|
+
const [isCreateCustomTypeModalOpen, setIsCreateCustomTypeModalOpen] =
|
|
34
|
+
useState(false);
|
|
45
35
|
|
|
46
36
|
return (
|
|
47
37
|
<>
|
|
@@ -101,7 +91,9 @@ export const CustomTypesTablePage: FC<CustomTypesTablePageProps> = ({
|
|
|
101
91
|
<Button
|
|
102
92
|
data-cy="create-ct"
|
|
103
93
|
loading={isCreatingCustomType}
|
|
104
|
-
onClick={
|
|
94
|
+
onClick={() => {
|
|
95
|
+
setIsCreateCustomTypeModalOpen(true);
|
|
96
|
+
}}
|
|
105
97
|
startIcon="add"
|
|
106
98
|
>
|
|
107
99
|
Create
|
|
@@ -113,8 +105,17 @@ export const CustomTypesTablePage: FC<CustomTypesTablePageProps> = ({
|
|
|
113
105
|
<CustomTypesTable
|
|
114
106
|
format={format}
|
|
115
107
|
isCreatingCustomType={isCreatingCustomType}
|
|
108
|
+
openCreateCustomTypeModal={() => {
|
|
109
|
+
setIsCreateCustomTypeModalOpen(true);
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
<CreateCustomTypeModal
|
|
113
|
+
format={format}
|
|
114
|
+
isCreating={isCreatingCustomType}
|
|
115
|
+
isOpen={isCreateCustomTypeModalOpen}
|
|
116
|
+
onCreateChange={setIsCreatingCustomType}
|
|
117
|
+
onOpenChange={setIsCreateCustomTypeModalOpen}
|
|
116
118
|
/>
|
|
117
|
-
<CreateCustomTypeModal format={format} />
|
|
118
119
|
</Box>
|
|
119
120
|
</AppLayoutContent>
|
|
120
121
|
</AppLayout>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { toast } from "react-toastify";
|
|
2
2
|
import { SharedSlice } from "@prismicio/types-internal/lib/customtypes";
|
|
3
3
|
|
|
4
|
-
import { pascalize
|
|
4
|
+
import { pascalize } from "@lib/utils/str";
|
|
5
5
|
import { managerClient } from "@src/managerClient";
|
|
6
6
|
import { telemetry } from "@src/apiClient";
|
|
7
|
+
import { buildEmptySliceModel } from "@src/domain/slice";
|
|
7
8
|
|
|
8
9
|
type CreateSliceArgs = {
|
|
9
10
|
sliceName: string;
|
|
@@ -12,8 +13,9 @@ type CreateSliceArgs = {
|
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
export async function createSlice(args: CreateSliceArgs) {
|
|
16
|
+
const { sliceName, libraryName, onSuccess } = args;
|
|
17
|
+
|
|
15
18
|
try {
|
|
16
|
-
const { sliceName, libraryName, onSuccess } = args;
|
|
17
19
|
const newSlice = buildEmptySliceModel(sliceName);
|
|
18
20
|
const { errors } = await managerClient.slices.createSlice({
|
|
19
21
|
libraryID: libraryName,
|
|
@@ -33,34 +35,8 @@ export async function createSlice(args: CreateSliceArgs) {
|
|
|
33
35
|
|
|
34
36
|
await onSuccess(newSlice);
|
|
35
37
|
} catch (e) {
|
|
36
|
-
const errorMessage =
|
|
38
|
+
const errorMessage = `An unexpected error happened while creating slice ${sliceName}.`;
|
|
37
39
|
console.error(errorMessage, e);
|
|
38
40
|
toast.error(errorMessage);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
|
|
42
|
-
const DEFAULT_VARIATION_ID = "default";
|
|
43
|
-
|
|
44
|
-
function buildEmptySliceModel(sliceName: string): SharedSlice {
|
|
45
|
-
return {
|
|
46
|
-
id: snakelize(sliceName),
|
|
47
|
-
type: "SharedSlice",
|
|
48
|
-
name: sliceName,
|
|
49
|
-
description: sliceName,
|
|
50
|
-
variations: [
|
|
51
|
-
{
|
|
52
|
-
id: DEFAULT_VARIATION_ID,
|
|
53
|
-
name: pascalize(DEFAULT_VARIATION_ID),
|
|
54
|
-
// Property not used yet. Fallback to "...".
|
|
55
|
-
docURL: "...",
|
|
56
|
-
// "initial" is fine here as default value.
|
|
57
|
-
version: "initial",
|
|
58
|
-
description: pascalize(DEFAULT_VARIATION_ID),
|
|
59
|
-
// Empty string is fine, we don't want to save imageUrl.
|
|
60
|
-
// We don't want to compare local and remote image with imageUrl.
|
|
61
|
-
// It will be striped anyway when doing the comparison.
|
|
62
|
-
imageUrl: "",
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { toast } from "react-toastify";
|
|
2
|
+
|
|
3
|
+
import { managerClient } from "@src/managerClient";
|
|
4
|
+
|
|
5
|
+
type DeleteSliceArgs = {
|
|
6
|
+
libraryID: string;
|
|
7
|
+
sliceID: string;
|
|
8
|
+
sliceName: string;
|
|
9
|
+
onSuccess: () => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export async function deleteSlice(args: DeleteSliceArgs) {
|
|
13
|
+
const { sliceName, sliceID, libraryID, onSuccess } = args;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const { errors } = await managerClient.slices.deleteSlice({
|
|
17
|
+
libraryID,
|
|
18
|
+
sliceID,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (errors.length > 0) {
|
|
22
|
+
throw errors;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onSuccess();
|
|
26
|
+
|
|
27
|
+
toast.success(`Successfully deleted slice “${sliceName}”`);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
const errorMessage = `An unexpected error happened while deleting slice “${sliceName}”.`;
|
|
30
|
+
console.error(errorMessage, e);
|
|
31
|
+
toast.error(errorMessage);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { toast } from "react-toastify";
|
|
2
|
+
|
|
3
|
+
import { managerClient } from "@src/managerClient";
|
|
4
|
+
import { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
5
|
+
import { rename } from "@src/domain/slice";
|
|
6
|
+
import { Slices } from "@lib/models/common/Slice";
|
|
7
|
+
|
|
8
|
+
type DeleteSliceArgs = {
|
|
9
|
+
newSliceName: string;
|
|
10
|
+
slice: ComponentUI;
|
|
11
|
+
onSuccess: (renamedSlice: ComponentUI) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export async function renameSlice(args: DeleteSliceArgs) {
|
|
15
|
+
const { slice, newSliceName, onSuccess } = args;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const renamedSlice = rename(slice, newSliceName);
|
|
19
|
+
|
|
20
|
+
const { errors } = await managerClient.slices.renameSlice({
|
|
21
|
+
libraryID: slice.from,
|
|
22
|
+
model: Slices.fromSM(renamedSlice.model),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (errors.length > 0) {
|
|
26
|
+
throw errors;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onSuccess(renamedSlice);
|
|
30
|
+
|
|
31
|
+
toast.success("Slice name updated");
|
|
32
|
+
} catch (e) {
|
|
33
|
+
const errorMessage = `An unexpected error happened while renaming “${slice.model.name}”.`;
|
|
34
|
+
console.error(errorMessage, e);
|
|
35
|
+
toast.error(errorMessage);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
import { Reducer } from "redux";
|
|
2
2
|
import { AvailableCustomTypesStoreType } from "./types";
|
|
3
|
-
import {
|
|
4
|
-
ActionType,
|
|
5
|
-
createAction,
|
|
6
|
-
createAsyncAction,
|
|
7
|
-
getType,
|
|
8
|
-
} from "typesafe-actions";
|
|
3
|
+
import { ActionType, createAction, getType } from "typesafe-actions";
|
|
9
4
|
import { SliceMachineStoreType } from "@src/redux/type";
|
|
10
5
|
import { refreshStateCreator } from "@src/modules/environment";
|
|
11
|
-
import { call, fork, put, takeLatest } from "redux-saga/effects";
|
|
12
|
-
import { withLoader } from "@src/modules/loading";
|
|
13
|
-
import { LoadingKeysEnum } from "@src/modules/loading/types";
|
|
14
|
-
import { updateCustomType } from "@src/apiClient";
|
|
15
|
-
import { modalCloseCreator } from "@src/modules/modal";
|
|
16
|
-
import { push } from "connected-next-router";
|
|
17
|
-
import { createCustomType } from "@src/features/customTypes/customTypesTable/createCustomType";
|
|
18
|
-
import { openToasterCreator, ToasterType } from "@src/modules/toaster";
|
|
19
6
|
import { CustomTypeSM } from "@lib/models/common/CustomType";
|
|
20
7
|
import {
|
|
21
8
|
normalizeFrontendCustomType,
|
|
22
9
|
normalizeFrontendCustomTypes,
|
|
23
10
|
} from "@lib/models/common/normalizers/customType";
|
|
24
11
|
import { omit } from "lodash";
|
|
25
|
-
import {
|
|
12
|
+
import { sliceDeleteSuccess } from "../slices";
|
|
26
13
|
import { filterSliceFromCustomType } from "@lib/utils/shared/customTypes";
|
|
27
14
|
import {
|
|
28
15
|
LocalOrRemoteCustomType,
|
|
@@ -30,63 +17,37 @@ import {
|
|
|
30
17
|
hasLocal,
|
|
31
18
|
hasLocalAndRemote,
|
|
32
19
|
} from "@lib/models/common/ModelData";
|
|
33
|
-
import { CustomTypeFormat } from "@slicemachine/manager";
|
|
34
|
-
import { CUSTOM_TYPES_CONFIG } from "@src/features/customTypes/customTypesConfig";
|
|
35
|
-
import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
|
|
36
|
-
import { CustomTypes } from "@lib/models/common/CustomType";
|
|
37
|
-
import { ToastMessageWithPath } from "@components/ToasterContainer";
|
|
38
|
-
|
|
39
|
-
export const saveCustomTypeCreator = createAsyncAction(
|
|
40
|
-
"CUSTOM_TYPE/SAVE.REQUEST",
|
|
41
|
-
"CUSTOM_TYPE/SAVE.RESPONSE",
|
|
42
|
-
"CUSTOM_TYPE/SAVE.FAILURE",
|
|
43
|
-
)<undefined, { customType: CustomTypeSM }>();
|
|
44
20
|
|
|
45
21
|
// Action Creators
|
|
46
|
-
export const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"CUSTOM_TYPES/CREATE.FAILURE",
|
|
50
|
-
)<
|
|
51
|
-
{
|
|
52
|
-
id: string;
|
|
53
|
-
label: string;
|
|
54
|
-
repeatable: boolean;
|
|
55
|
-
format: CustomTypeFormat;
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
newCustomType: CustomTypeSM;
|
|
59
|
-
}
|
|
60
|
-
>();
|
|
22
|
+
export const customTypeSaveSuccess = createAction("CUSTOM_TYPE/SAVE_SUCCESS")<{
|
|
23
|
+
newCustomType: CustomTypeSM;
|
|
24
|
+
}>();
|
|
61
25
|
|
|
62
|
-
export const
|
|
63
|
-
"CUSTOM_TYPES/
|
|
26
|
+
export const customTypeCreateSuccess = createAction(
|
|
27
|
+
"CUSTOM_TYPES/CREATE_SUCCESS",
|
|
28
|
+
)<{
|
|
29
|
+
newCustomType: CustomTypeSM;
|
|
30
|
+
}>();
|
|
31
|
+
|
|
32
|
+
export const customTypeRenameSuccess = createAction(
|
|
33
|
+
"CUSTOM_TYPES/RENAME_SUCCESS",
|
|
64
34
|
)<{
|
|
65
35
|
renamedCustomType: CustomTypeSM;
|
|
66
36
|
}>();
|
|
67
37
|
|
|
68
|
-
export const
|
|
69
|
-
"CUSTOM_TYPES/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
)
|
|
73
|
-
{
|
|
74
|
-
customTypeId: string;
|
|
75
|
-
customTypeName: string;
|
|
76
|
-
format: CustomTypeFormat;
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
customTypeId: string;
|
|
80
|
-
}
|
|
81
|
-
>();
|
|
38
|
+
export const customTypeDeleteSuccess = createAction(
|
|
39
|
+
"CUSTOM_TYPES/DELETE_SUCCESS",
|
|
40
|
+
)<{
|
|
41
|
+
customTypeId: string;
|
|
42
|
+
}>();
|
|
82
43
|
|
|
83
44
|
type CustomTypesActions =
|
|
84
45
|
| ActionType<typeof refreshStateCreator>
|
|
85
|
-
| ActionType<typeof
|
|
86
|
-
| ActionType<typeof
|
|
87
|
-
| ActionType<typeof
|
|
88
|
-
| ActionType<typeof
|
|
89
|
-
| ActionType<typeof
|
|
46
|
+
| ActionType<typeof customTypeCreateSuccess>
|
|
47
|
+
| ActionType<typeof customTypeRenameSuccess>
|
|
48
|
+
| ActionType<typeof customTypeSaveSuccess>
|
|
49
|
+
| ActionType<typeof customTypeDeleteSuccess>
|
|
50
|
+
| ActionType<typeof sliceDeleteSuccess>;
|
|
90
51
|
|
|
91
52
|
// Selectors
|
|
92
53
|
export const selectAllCustomTypes = (
|
|
@@ -134,7 +95,7 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
134
95
|
...normalizedNewCustomType,
|
|
135
96
|
};
|
|
136
97
|
}
|
|
137
|
-
case getType(
|
|
98
|
+
case getType(customTypeCreateSuccess): {
|
|
138
99
|
const normalizedNewCustomType = normalizeFrontendCustomType(
|
|
139
100
|
action.payload.newCustomType,
|
|
140
101
|
);
|
|
@@ -145,8 +106,8 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
145
106
|
};
|
|
146
107
|
}
|
|
147
108
|
|
|
148
|
-
case getType(
|
|
149
|
-
const localCustomType = action.payload.
|
|
109
|
+
case getType(customTypeSaveSuccess): {
|
|
110
|
+
const localCustomType = action.payload.newCustomType;
|
|
150
111
|
|
|
151
112
|
return {
|
|
152
113
|
...state,
|
|
@@ -157,7 +118,7 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
157
118
|
};
|
|
158
119
|
}
|
|
159
120
|
|
|
160
|
-
case getType(
|
|
121
|
+
case getType(customTypeRenameSuccess): {
|
|
161
122
|
const id = action.payload.renamedCustomType.id;
|
|
162
123
|
const customType = state[id];
|
|
163
124
|
|
|
@@ -172,7 +133,7 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
172
133
|
};
|
|
173
134
|
}
|
|
174
135
|
|
|
175
|
-
case getType(
|
|
136
|
+
case getType(customTypeDeleteSuccess): {
|
|
176
137
|
const customType = state[action.payload.customTypeId];
|
|
177
138
|
|
|
178
139
|
if (hasLocalAndRemote(customType)) {
|
|
@@ -191,7 +152,7 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
191
152
|
return state;
|
|
192
153
|
}
|
|
193
154
|
|
|
194
|
-
case getType(
|
|
155
|
+
case getType(sliceDeleteSuccess): {
|
|
195
156
|
const sliceId = action.payload.sliceId;
|
|
196
157
|
|
|
197
158
|
const customTypesUpdated: AvailableCustomTypesStoreType = Object.entries(
|
|
@@ -229,70 +190,3 @@ export const availableCustomTypesReducer: Reducer<
|
|
|
229
190
|
return state;
|
|
230
191
|
}
|
|
231
192
|
};
|
|
232
|
-
|
|
233
|
-
export function* createCustomTypeSaga({
|
|
234
|
-
payload,
|
|
235
|
-
}: ReturnType<typeof createCustomTypeCreator.request>) {
|
|
236
|
-
const customTypesConfig = CUSTOM_TYPES_CONFIG[payload.format];
|
|
237
|
-
const customTypesMessages = CUSTOM_TYPES_MESSAGES[payload.format];
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
const newCustomType = CustomTypes.toSM(
|
|
241
|
-
createCustomType(
|
|
242
|
-
payload.id,
|
|
243
|
-
payload.label,
|
|
244
|
-
payload.repeatable,
|
|
245
|
-
payload.format,
|
|
246
|
-
),
|
|
247
|
-
);
|
|
248
|
-
yield call(updateCustomType, CustomTypes.fromSM(newCustomType));
|
|
249
|
-
yield put(createCustomTypeCreator.success({ newCustomType }));
|
|
250
|
-
yield put(modalCloseCreator());
|
|
251
|
-
yield put(
|
|
252
|
-
push({
|
|
253
|
-
pathname: customTypesConfig.getBuilderPagePathname(payload.id),
|
|
254
|
-
query:
|
|
255
|
-
newCustomType.format === "page"
|
|
256
|
-
? {
|
|
257
|
-
newPageType: true,
|
|
258
|
-
}
|
|
259
|
-
: undefined,
|
|
260
|
-
}),
|
|
261
|
-
);
|
|
262
|
-
yield put(
|
|
263
|
-
openToasterCreator({
|
|
264
|
-
content: ToastMessageWithPath({
|
|
265
|
-
message: `${customTypesMessages.name({
|
|
266
|
-
start: true,
|
|
267
|
-
plural: false,
|
|
268
|
-
})} saved successfully at `,
|
|
269
|
-
path: `./customtypes/${newCustomType.id}/index.json`,
|
|
270
|
-
}),
|
|
271
|
-
type: ToasterType.SUCCESS,
|
|
272
|
-
}),
|
|
273
|
-
);
|
|
274
|
-
} catch (e) {
|
|
275
|
-
yield put(
|
|
276
|
-
openToasterCreator({
|
|
277
|
-
content: `Internal Error: ${customTypesMessages.name({
|
|
278
|
-
start: true,
|
|
279
|
-
plural: false,
|
|
280
|
-
})} not saved`,
|
|
281
|
-
type: ToasterType.ERROR,
|
|
282
|
-
}),
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Saga watchers
|
|
288
|
-
function* handleCustomTypeRequests() {
|
|
289
|
-
yield takeLatest(
|
|
290
|
-
getType(createCustomTypeCreator.request),
|
|
291
|
-
withLoader(createCustomTypeSaga, LoadingKeysEnum.CREATE_CUSTOM_TYPE),
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Saga Exports
|
|
296
|
-
export function* watchAvailableCustomTypesSagas() {
|
|
297
|
-
yield fork(handleCustomTypeRequests);
|
|
298
|
-
}
|