slice-machine-ui 1.23.2-beta.1 → 1.23.2-beta.11
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/.depcheckrc +3 -0
- package/components/ChangesEmptyState/OfflinePage.tsx +1 -1
- package/components/ChangesItems/ChangesItems.tsx +6 -2
- package/components/CustomTypeTable/changesPage.tsx +12 -7
- package/components/DeleteSliceModal/index.tsx +37 -24
- package/components/DeleteVariationModal/index.tsx +1 -0
- package/components/Forms/CreateCustomTypeModal/CreateCustomTypeModal.tsx +65 -38
- package/components/Forms/CreateSliceModal/CreateSliceModal.tsx +3 -1
- package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +7 -2
- package/components/Forms/RenameSliceModal/RenameSliceModal.tsx +36 -21
- package/components/Forms/RenameVariationModal/RenameVariationModal.tsx +0 -1
- package/components/LoginModal/index.tsx +40 -2
- package/components/ModalFormCard/index.tsx +0 -1
- package/components/Navigation/ChangesItem.tsx +117 -0
- package/components/Navigation/Environment.tsx +51 -4
- package/components/Navigation/index.css.ts +1 -2
- package/components/Navigation/index.test.tsx +5 -85
- package/components/Navigation/index.tsx +32 -20
- package/components/ReviewModal/ReviewForm.tsx +0 -1
- package/lib/builders/SliceBuilder/index.tsx +3 -3
- package/lib/builders/common/EditModal/Form.jsx +0 -1
- package/lib/builders/common/Zone/Card/components/NewField.tsx +0 -1
- package/lib/models/common/ModelStatus/index.ts +25 -0
- package/lib/models/common/widgets/StructuredText/index.ts +1 -1
- package/out/404.html +1 -1
- package/out/_next/static/chunks/18539003-5f78714a35fde4a1.js +97 -0
- package/out/_next/static/chunks/25-3aa4d4b24167d340.js +1 -0
- package/out/_next/static/chunks/318-19dbcae10cdb6408.js +1 -0
- package/out/_next/static/chunks/727-de03055e40815a3a.js +1 -0
- package/out/_next/static/chunks/777-8c5507e3b119b5dc.js +8 -0
- package/out/_next/static/chunks/799-0af1215eb2b3c17e.js +1 -0
- package/out/_next/static/chunks/904-40686b0426716111.js +1 -0
- package/out/_next/static/chunks/pages/_app-bca191df4ac7078e.js +434 -0
- package/out/_next/static/chunks/pages/{changelog-afd18276fe018b24.js → changelog-cb1df3a70b20f1b8.js} +1 -1
- package/out/_next/static/chunks/pages/changes-ccfd715c2bdc4f83.js +1 -0
- 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/{labs-ee206005948f8e87.js → labs-2adfb5127f9c4081.js} +1 -1
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-d1ffca11c42f2603.js → [pageTypeId]-84a22c5e480d3fa9.js} +1 -1
- package/out/_next/static/chunks/pages/settings-94bcd7422e8b237d.js +1 -0
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/{simulator-897ca93c114a1435.js → simulator-aaf65fbec8f5839c.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-90bb2ea76d2abf42.js +1 -0
- package/out/_next/static/chunks/pages/slices-e0ce615c38e8338d.js +1 -0
- package/out/_next/static/css/39e089aad1742a3a.css +1 -0
- package/out/_next/static/css/{37153180c3b0dd66.css → 838fd8bb5a7c32b0.css} +1 -1
- package/out/_next/static/css/ca32882a5d2d8d88.css +1 -0
- package/out/_next/static/dS_xZnzzna6Y6uwcTgf90/_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/settings.html +1 -0
- 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 +9 -6
- package/pages/_app.tsx +34 -32
- package/pages/changes.tsx +27 -41
- package/pages/settings.tsx +1 -0
- package/pages/slices.tsx +20 -8
- package/postcss.config.js +10 -0
- package/src/apiClient.ts +1 -22
- package/src/components/FieldSet/FieldSet.stories.tsx +20 -11
- package/src/components/RelativeTime/RelativeTime.stories.tsx +25 -0
- package/src/components/RelativeTime/RelativeTime.tsx +40 -0
- package/src/components/RelativeTime/index.ts +1 -0
- package/src/components/SideNav/SideNav.css.ts +1 -1
- package/src/components/SideNav/SideNav.tsx +9 -5
- package/src/components/SideNav/SideNavEnvironmentSelector.tsx +31 -11
- package/src/domain/__tests__/customType.test.ts +205 -19
- package/src/domain/customType.ts +132 -7
- package/src/domain/slice.ts +38 -0
- package/src/features/autoSave/AutoSaveStatusIndicator.tsx +4 -4
- 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/CustomTypeProvider.tsx +11 -10
- package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +5 -3
- package/src/features/customTypes/customTypesTable/CustomTypesTable.tsx +8 -8
- package/src/features/customTypes/customTypesTable/CustomTypesTablePage.tsx +18 -17
- package/src/features/environments/actions/setEnvironment.ts +4 -4
- package/src/features/settings/SettingsPage.tsx +47 -0
- package/src/features/settings/git/ConnectGitRepository.tsx +126 -0
- package/src/features/settings/git/ConnectGitRepositoryBlankSlate.tsx +33 -0
- package/src/features/settings/git/GitOwnerSelect.tsx +71 -0
- package/src/features/settings/git/GitProvider.ts +40 -0
- package/src/features/settings/git/GitProviderConnectButtons.tsx +63 -0
- package/src/features/settings/git/GitRepositoriesList.tsx +76 -0
- package/src/features/settings/git/GitRepositoriesSearch.tsx +69 -0
- package/src/features/settings/git/GitRepositoryConnectDialog.tsx +85 -0
- package/src/features/settings/git/GitRepositoryDisconnectDialog.tsx +60 -0
- package/src/features/settings/git/useGitIntegrationExperiment.ts +8 -0
- package/src/features/settings/git/useGitOwners.ts +12 -0
- package/src/features/settings/git/useGitRepos.ts +24 -0
- package/src/features/settings/git/useLinkedGitRepos.ts +41 -0
- package/src/features/settings/git/useWriteAPIToken.ts +23 -0
- 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/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx +0 -1
- package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx +0 -1
- package/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx +0 -1
- package/src/features/slices/sliceBuilder/SliceBuilderProvider.tsx +12 -10
- package/src/features/sync/AutoSyncProvider.tsx +252 -0
- package/src/features/sync/components/AutoSyncStatusIndicator.module.css +17 -0
- package/src/features/sync/components/AutoSyncStatusIndicator.module.css.d.ts +5 -0
- package/src/features/sync/components/AutoSyncStatusIndicator.tsx +58 -0
- package/src/features/sync/fetchUnSyncChanges.ts +40 -0
- package/src/features/sync/getUnSyncChanges.ts +144 -0
- package/src/features/sync/useUnSyncChanges.ts +32 -0
- package/src/hooks/useActionQueue.tsx +177 -0
- package/src/hooks/useAuthStatus.ts +12 -0
- package/src/hooks/useUser.ts +14 -0
- package/src/icons/SettingsIcon.tsx +19 -0
- package/src/icons/SyncFailed.tsx +30 -0
- package/src/icons/Synced.tsx +19 -0
- package/src/icons/Syncing.tsx +23 -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/__testutils__/index.tsx +8 -5
- package/test/src/modules/__fixtures__/serverState.ts +1 -2
- package/test/src/modules/availableCustomTypes/index.test.ts +2 -243
- package/test/src/modules/slices.test.ts +1 -267
- package/components/Navigation/ChangesListItem.tsx +0 -92
- package/components/Navigation/ChangesRightElement.tsx +0 -33
- package/out/_next/static/chunks/18539003-5cc559566b738915.js +0 -97
- package/out/_next/static/chunks/25-37d6fa7f064be04b.js +0 -1
- package/out/_next/static/chunks/318-ce7e74f18f2d5b22.js +0 -1
- package/out/_next/static/chunks/376-7e784d6069e01654.js +0 -8
- 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/_app-cd9d4c76a4abc11a.js +0 -432
- package/out/_next/static/chunks/pages/changes-2a976f9efeb719aa.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/out/_next/static/css/200244e3e0463c39.css +0 -1
- package/out/_next/static/m6psnC5u1xT7Y6osWHKjp/_buildManifest.js +0 -1
- package/src/features/autoSave/useAutoSave.tsx +0 -177
- package/src/features/customTypes/__tests__/createCustomType.test.ts +0 -159
- package/src/features/customTypes/customTypesTable/createCustomType.ts +0 -107
- package/src/features/legacyState/actions/getLegacySliceMachineState.ts +0 -53
- package/src/features/legacyState/useLegacySliceMachineState.ts +0 -7
- package/src/hooks/useModelStatus.ts +0 -78
- package/src/hooks/useUnSyncChanges.ts +0 -88
- package/test/components/CreateCustomTypeModal.test.tsx +0 -73
- package/test/components/LoginModal.test.tsx +0 -67
- package/test/src/hooks/useModelStatus.test.ts +0 -115
- /package/out/_next/static/{m6psnC5u1xT7Y6osWHKjp → dS_xZnzzna6Y6uwcTgf90}/_ssgManifest.js +0 -0
- /package/src/features/{changes → sync}/actions/pushChanges.ts +0 -0
- /package/src/features/{changes → sync}/actions/trackPushChangesSuccess.ts +0 -0
package/src/domain/slice.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CompositeSlice,
|
|
3
3
|
LegacySlice,
|
|
4
|
+
SharedSlice,
|
|
4
5
|
} from "@prismicio/types-internal/lib/customtypes/widgets/slices";
|
|
5
6
|
import { NestableWidget } from "@prismicio/types-internal/lib/customtypes";
|
|
6
7
|
|
|
7
8
|
import type { ComponentUI } from "@lib/models/common/ComponentUI";
|
|
8
9
|
import type { VariationSM, WidgetsArea } from "@lib/models/common/Slice";
|
|
10
|
+
import { pascalize, snakelize } from "@lib/utils/str";
|
|
9
11
|
|
|
10
12
|
type CopySliceVariationArgs = {
|
|
11
13
|
copiedVariation: VariationSM;
|
|
@@ -46,6 +48,8 @@ type ReorderFieldArgs = {
|
|
|
46
48
|
destinationIndex: number;
|
|
47
49
|
};
|
|
48
50
|
|
|
51
|
+
const DEFAULT_VARIATION_ID = "default";
|
|
52
|
+
|
|
49
53
|
export function countMissingScreenshots(slice: ComponentUI): number {
|
|
50
54
|
return slice.model.variations.length - Object.keys(slice.screenshots).length;
|
|
51
55
|
}
|
|
@@ -243,3 +247,37 @@ export function reorderField(args: ReorderFieldArgs): ComponentUI {
|
|
|
243
247
|
},
|
|
244
248
|
};
|
|
245
249
|
}
|
|
250
|
+
|
|
251
|
+
export function buildEmptySliceModel(sliceName: string): SharedSlice {
|
|
252
|
+
return {
|
|
253
|
+
id: snakelize(sliceName),
|
|
254
|
+
type: "SharedSlice",
|
|
255
|
+
name: sliceName,
|
|
256
|
+
description: sliceName,
|
|
257
|
+
variations: [
|
|
258
|
+
{
|
|
259
|
+
id: DEFAULT_VARIATION_ID,
|
|
260
|
+
name: pascalize(DEFAULT_VARIATION_ID),
|
|
261
|
+
// Property not used yet. Fallback to "...".
|
|
262
|
+
docURL: "...",
|
|
263
|
+
// "initial" is fine here as default value.
|
|
264
|
+
version: "initial",
|
|
265
|
+
description: pascalize(DEFAULT_VARIATION_ID),
|
|
266
|
+
// Empty string is fine, we don't want to save imageUrl.
|
|
267
|
+
// We don't want to compare local and remote image with imageUrl.
|
|
268
|
+
// It will be striped anyway when doing the comparison.
|
|
269
|
+
imageUrl: "",
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function rename(slice: ComponentUI, newSliceName: string): ComponentUI {
|
|
276
|
+
return {
|
|
277
|
+
...slice,
|
|
278
|
+
model: {
|
|
279
|
+
...slice.model,
|
|
280
|
+
name: newSliceName,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
import { Box, Icon, ProgressCircle, Text } from "@prismicio/editor-ui";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { ActionQueueStatus } from "@src/hooks/useActionQueue";
|
|
5
5
|
|
|
6
6
|
type AutoSaveStatusIndicatorProps = {
|
|
7
|
-
status:
|
|
7
|
+
status: ActionQueueStatus;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export const AutoSaveStatusIndicator: FC<AutoSaveStatusIndicatorProps> = (
|
|
@@ -14,7 +14,7 @@ export const AutoSaveStatusIndicator: FC<AutoSaveStatusIndicatorProps> = (
|
|
|
14
14
|
let autoSaveStatusInfo;
|
|
15
15
|
|
|
16
16
|
switch (status) {
|
|
17
|
-
case "
|
|
17
|
+
case "pending":
|
|
18
18
|
autoSaveStatusInfo = {
|
|
19
19
|
icon: <ProgressCircle color="grey11" />,
|
|
20
20
|
text: "Saving...",
|
|
@@ -26,7 +26,7 @@ export const AutoSaveStatusIndicator: FC<AutoSaveStatusIndicatorProps> = (
|
|
|
26
26
|
text: "Failed to save",
|
|
27
27
|
};
|
|
28
28
|
break;
|
|
29
|
-
case "
|
|
29
|
+
case "done":
|
|
30
30
|
autoSaveStatusInfo = {
|
|
31
31
|
icon: <Icon name="check" color="green11" size="medium" />,
|
|
32
32
|
text: "Auto-saved",
|
|
@@ -1,35 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useSelector } from "react-redux";
|
|
1
|
+
import { useState } from "react";
|
|
3
2
|
import { Box, Button, Text } from "@prismicio/editor-ui";
|
|
4
3
|
import { cache } from "@prismicio/editor-support/Suspense";
|
|
5
4
|
|
|
6
5
|
import { CreateCustomTypeModal } from "@components/Forms/CreateCustomTypeModal";
|
|
7
|
-
import { SliceMachineStoreType } from "@src/redux/type";
|
|
8
|
-
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
9
|
-
import { LoadingKeysEnum } from "@src/modules/loading/types";
|
|
10
|
-
import { isLoading } from "@src/modules/loading";
|
|
11
6
|
import { BlankPageIcon } from "@src/icons/BlankPageIcon";
|
|
12
7
|
import { getIsEmptyProject } from "@src/hooks/useIsEmptyProject";
|
|
13
8
|
|
|
14
9
|
export function PageTypeOnboarding() {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
(
|
|
18
|
-
isCreatingCustomType: isLoading(
|
|
19
|
-
store,
|
|
20
|
-
LoadingKeysEnum.CREATE_CUSTOM_TYPE,
|
|
21
|
-
),
|
|
22
|
-
}),
|
|
23
|
-
);
|
|
24
|
-
// State to ensure button loader is still visible while redirecting
|
|
25
|
-
const [isButtonLoading, setIsButtonLoading] = useState(false);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (isCreatingCustomType) {
|
|
29
|
-
setIsButtonLoading(true);
|
|
30
|
-
cache.clear(getIsEmptyProject, []);
|
|
31
|
-
}
|
|
32
|
-
}, [isCreatingCustomType]);
|
|
10
|
+
const [isCreatingCustomType, setIsCreatingCustomType] = useState(false);
|
|
11
|
+
const [isCreateCustomTypeModalOpen, setIsCreateCustomTypeModalOpen] =
|
|
12
|
+
useState(false);
|
|
33
13
|
|
|
34
14
|
return (
|
|
35
15
|
<Box
|
|
@@ -53,10 +33,25 @@ export function PageTypeOnboarding() {
|
|
|
53
33
|
Welcome to Slice Machine. Your journey starts with your first page
|
|
54
34
|
type — the model that you will use to create pages for your website.
|
|
55
35
|
</Text>
|
|
56
|
-
<Button
|
|
36
|
+
<Button
|
|
37
|
+
loading={isCreatingCustomType}
|
|
38
|
+
onClick={() => {
|
|
39
|
+
setIsCreateCustomTypeModalOpen(true);
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
57
42
|
Create a page type
|
|
58
43
|
</Button>
|
|
59
|
-
<CreateCustomTypeModal
|
|
44
|
+
<CreateCustomTypeModal
|
|
45
|
+
format="page"
|
|
46
|
+
isCreating={isCreatingCustomType}
|
|
47
|
+
isOpen={isCreateCustomTypeModalOpen}
|
|
48
|
+
origin="onboarding"
|
|
49
|
+
onCreateChange={(isCreating) => {
|
|
50
|
+
setIsCreatingCustomType(isCreating);
|
|
51
|
+
cache.clear(getIsEmptyProject, []);
|
|
52
|
+
}}
|
|
53
|
+
onOpenChange={setIsCreateCustomTypeModalOpen}
|
|
54
|
+
/>
|
|
60
55
|
</Box>
|
|
61
56
|
</Box>
|
|
62
57
|
);
|
|
@@ -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
|
}
|
|
@@ -10,18 +10,16 @@ import { CustomType } from "@prismicio/types-internal/lib/customtypes";
|
|
|
10
10
|
import { useStableCallback } from "@prismicio/editor-support/React";
|
|
11
11
|
|
|
12
12
|
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
13
|
-
import {
|
|
14
|
-
AutoSaveStatus,
|
|
15
|
-
useAutoSave,
|
|
16
|
-
} from "@src/features/autoSave/useAutoSave";
|
|
13
|
+
import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
|
|
17
14
|
import { getFormat } from "@src/domain/customType";
|
|
18
15
|
import { updateCustomType } from "@src/apiClient";
|
|
16
|
+
import { ActionQueueStatus, useActionQueue } from "@src/hooks/useActionQueue";
|
|
19
17
|
|
|
20
18
|
import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";
|
|
21
19
|
|
|
22
20
|
type CustomTypeContext = {
|
|
23
21
|
customType: CustomType;
|
|
24
|
-
|
|
22
|
+
actionQueueStatus: ActionQueueStatus;
|
|
25
23
|
setCustomType: (customType: CustomType) => void;
|
|
26
24
|
};
|
|
27
25
|
|
|
@@ -40,16 +38,17 @@ export function CustomTypeProvider(props: CustomTypeProviderProps) {
|
|
|
40
38
|
const [customType, setCustomTypeState] = useState(initialCustomType);
|
|
41
39
|
const format = getFormat(customType);
|
|
42
40
|
const customTypeMessages = CUSTOM_TYPES_MESSAGES[format];
|
|
43
|
-
const {
|
|
41
|
+
const { actionQueueStatus, setNextAction } = useActionQueue({
|
|
44
42
|
errorMessage: customTypeMessages.autoSaveFailed,
|
|
45
43
|
});
|
|
46
44
|
const { saveCustomTypeSuccess } = useSliceMachineActions();
|
|
47
45
|
const stableSaveCustomTypeSuccess = useStableCallback(saveCustomTypeSuccess);
|
|
46
|
+
const { syncChanges } = useAutoSync();
|
|
48
47
|
|
|
49
48
|
const setCustomType = useCallback(
|
|
50
49
|
(customType: CustomType) => {
|
|
51
50
|
setCustomTypeState(customType);
|
|
52
|
-
|
|
51
|
+
setNextAction(async () => {
|
|
53
52
|
const { errors } = await updateCustomType(customType);
|
|
54
53
|
|
|
55
54
|
if (errors.length > 0) {
|
|
@@ -58,18 +57,20 @@ export function CustomTypeProvider(props: CustomTypeProviderProps) {
|
|
|
58
57
|
|
|
59
58
|
// Update available custom types store with new custom type
|
|
60
59
|
stableSaveCustomTypeSuccess(customType);
|
|
60
|
+
|
|
61
|
+
syncChanges();
|
|
61
62
|
});
|
|
62
63
|
},
|
|
63
|
-
[
|
|
64
|
+
[setNextAction, stableSaveCustomTypeSuccess, syncChanges],
|
|
64
65
|
);
|
|
65
66
|
|
|
66
67
|
const contextValue: CustomTypeContext = useMemo(
|
|
67
68
|
() => ({
|
|
68
|
-
|
|
69
|
+
actionQueueStatus,
|
|
69
70
|
customType,
|
|
70
71
|
setCustomType,
|
|
71
72
|
}),
|
|
72
|
-
[
|
|
73
|
+
[actionQueueStatus, customType, setCustomType],
|
|
73
74
|
);
|
|
74
75
|
|
|
75
76
|
return (
|
|
@@ -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
|
}
|
|
@@ -76,7 +78,7 @@ const CustomTypesBuilderPageWithProvider: React.FC<
|
|
|
76
78
|
<CustomTypeProvider
|
|
77
79
|
initialCustomType={CustomTypes.fromSM(customTypeFromStore)}
|
|
78
80
|
>
|
|
79
|
-
{({
|
|
81
|
+
{({ actionQueueStatus, customType, setCustomType }) => {
|
|
80
82
|
const format = getFormat(customType);
|
|
81
83
|
const config = CUSTOM_TYPES_CONFIG[customTypeFromStore.format];
|
|
82
84
|
const messages = CUSTOM_TYPES_MESSAGES[customTypeFromStore.format];
|
|
@@ -90,7 +92,7 @@ const CustomTypesBuilderPageWithProvider: React.FC<
|
|
|
90
92
|
page={customType.label ?? customType.id}
|
|
91
93
|
/>
|
|
92
94
|
<AppLayoutActions>
|
|
93
|
-
<AutoSaveStatusIndicator status={
|
|
95
|
+
<AutoSaveStatusIndicator status={actionQueueStatus} />
|
|
94
96
|
{customType.format === "page" ? (
|
|
95
97
|
<PageSnippetDialog model={customType} />
|
|
96
98
|
) : undefined}
|
|
@@ -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,8 +1,8 @@
|
|
|
1
1
|
import { revalidateData } from "@prismicio/editor-support/Suspense";
|
|
2
|
-
import { Environment } from "@slicemachine/manager/client";
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import { Environment } from "@slicemachine/manager/client";
|
|
5
4
|
import { managerClient } from "@src/managerClient";
|
|
5
|
+
import { getState } from "@src/apiClient";
|
|
6
6
|
|
|
7
7
|
import { getActiveEnvironment } from "./getActiveEnvironment";
|
|
8
8
|
|
|
@@ -13,6 +13,6 @@ export async function setEnvironment(
|
|
|
13
13
|
environment: environment.domain,
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
revalidateData(getActiveEnvironment, []);
|
|
17
|
-
revalidateData(
|
|
16
|
+
void revalidateData(getActiveEnvironment, []);
|
|
17
|
+
void revalidateData(getState, []);
|
|
18
18
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Box } from "@prismicio/editor-ui";
|
|
2
|
+
import Head from "next/head";
|
|
3
|
+
import { useRouter } from "next/router";
|
|
4
|
+
import { type FC, useEffect } from "react";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
AppLayout,
|
|
8
|
+
AppLayoutBreadcrumb,
|
|
9
|
+
AppLayoutContent,
|
|
10
|
+
AppLayoutHeader,
|
|
11
|
+
} from "@components/AppLayout";
|
|
12
|
+
import { ConnectGitRepository } from "@src/features/settings/git/ConnectGitRepository";
|
|
13
|
+
import { useGitIntegrationExperiment } from "@src/features/settings/git/useGitIntegrationExperiment";
|
|
14
|
+
|
|
15
|
+
export const SettingsPage: FC = () => {
|
|
16
|
+
const gitIntegrationExperiment = useGitIntegrationExperiment();
|
|
17
|
+
const router = useRouter();
|
|
18
|
+
|
|
19
|
+
// TODO(DT-1801): implement a 404 page.
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!gitIntegrationExperiment.eligible) {
|
|
22
|
+
void router.replace("/");
|
|
23
|
+
}
|
|
24
|
+
}, [gitIntegrationExperiment.eligible, router]);
|
|
25
|
+
|
|
26
|
+
if (!gitIntegrationExperiment.eligible) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<Head>
|
|
33
|
+
<title>Settings - Slice Machine</title>
|
|
34
|
+
</Head>
|
|
35
|
+
<AppLayout>
|
|
36
|
+
<AppLayoutHeader>
|
|
37
|
+
<AppLayoutBreadcrumb folder="Settings" />
|
|
38
|
+
</AppLayoutHeader>
|
|
39
|
+
<AppLayoutContent>
|
|
40
|
+
<Box flexDirection="column" maxWidth={600}>
|
|
41
|
+
<ConnectGitRepository />
|
|
42
|
+
</Box>
|
|
43
|
+
</AppLayoutContent>
|
|
44
|
+
</AppLayout>
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
};
|