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.
Files changed (164) hide show
  1. package/.depcheckrc +3 -0
  2. package/components/ChangesEmptyState/OfflinePage.tsx +1 -1
  3. package/components/ChangesItems/ChangesItems.tsx +6 -2
  4. package/components/CustomTypeTable/changesPage.tsx +12 -7
  5. package/components/DeleteSliceModal/index.tsx +37 -24
  6. package/components/DeleteVariationModal/index.tsx +1 -0
  7. package/components/Forms/CreateCustomTypeModal/CreateCustomTypeModal.tsx +65 -38
  8. package/components/Forms/CreateSliceModal/CreateSliceModal.tsx +3 -1
  9. package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +7 -2
  10. package/components/Forms/RenameSliceModal/RenameSliceModal.tsx +36 -21
  11. package/components/Forms/RenameVariationModal/RenameVariationModal.tsx +0 -1
  12. package/components/LoginModal/index.tsx +40 -2
  13. package/components/ModalFormCard/index.tsx +0 -1
  14. package/components/Navigation/ChangesItem.tsx +117 -0
  15. package/components/Navigation/Environment.tsx +51 -4
  16. package/components/Navigation/index.css.ts +1 -2
  17. package/components/Navigation/index.test.tsx +5 -85
  18. package/components/Navigation/index.tsx +32 -20
  19. package/components/ReviewModal/ReviewForm.tsx +0 -1
  20. package/lib/builders/SliceBuilder/index.tsx +3 -3
  21. package/lib/builders/common/EditModal/Form.jsx +0 -1
  22. package/lib/builders/common/Zone/Card/components/NewField.tsx +0 -1
  23. package/lib/models/common/ModelStatus/index.ts +25 -0
  24. package/lib/models/common/widgets/StructuredText/index.ts +1 -1
  25. package/out/404.html +1 -1
  26. package/out/_next/static/chunks/18539003-5f78714a35fde4a1.js +97 -0
  27. package/out/_next/static/chunks/25-3aa4d4b24167d340.js +1 -0
  28. package/out/_next/static/chunks/318-19dbcae10cdb6408.js +1 -0
  29. package/out/_next/static/chunks/727-de03055e40815a3a.js +1 -0
  30. package/out/_next/static/chunks/777-8c5507e3b119b5dc.js +8 -0
  31. package/out/_next/static/chunks/799-0af1215eb2b3c17e.js +1 -0
  32. package/out/_next/static/chunks/904-40686b0426716111.js +1 -0
  33. package/out/_next/static/chunks/pages/_app-bca191df4ac7078e.js +434 -0
  34. package/out/_next/static/chunks/pages/{changelog-afd18276fe018b24.js → changelog-cb1df3a70b20f1b8.js} +1 -1
  35. package/out/_next/static/chunks/pages/changes-ccfd715c2bdc4f83.js +1 -0
  36. package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-3f862ad6111a1fc0.js → [customTypeId]-97ab3b90b85d645d.js} +1 -1
  37. package/out/_next/static/chunks/pages/{custom-types-94b8f8dbf7727412.js → custom-types-3c8e721ec6802127.js} +1 -1
  38. package/out/_next/static/chunks/pages/index-cf93d16e9c63b6db.js +1 -0
  39. package/out/_next/static/chunks/pages/{labs-ee206005948f8e87.js → labs-2adfb5127f9c4081.js} +1 -1
  40. package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-d1ffca11c42f2603.js → [pageTypeId]-84a22c5e480d3fa9.js} +1 -1
  41. package/out/_next/static/chunks/pages/settings-94bcd7422e8b237d.js +1 -0
  42. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/{simulator-897ca93c114a1435.js → simulator-aaf65fbec8f5839c.js} +1 -1
  43. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-90bb2ea76d2abf42.js +1 -0
  44. package/out/_next/static/chunks/pages/slices-e0ce615c38e8338d.js +1 -0
  45. package/out/_next/static/css/39e089aad1742a3a.css +1 -0
  46. package/out/_next/static/css/{37153180c3b0dd66.css → 838fd8bb5a7c32b0.css} +1 -1
  47. package/out/_next/static/css/ca32882a5d2d8d88.css +1 -0
  48. package/out/_next/static/dS_xZnzzna6Y6uwcTgf90/_buildManifest.js +1 -0
  49. package/out/changelog.html +1 -1
  50. package/out/changes.html +1 -1
  51. package/out/custom-types/[customTypeId].html +1 -1
  52. package/out/custom-types.html +1 -1
  53. package/out/index.html +1 -1
  54. package/out/labs.html +1 -1
  55. package/out/page-types/[pageTypeId].html +1 -1
  56. package/out/settings.html +1 -0
  57. package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  58. package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
  59. package/out/slices.html +1 -1
  60. package/package.json +9 -6
  61. package/pages/_app.tsx +34 -32
  62. package/pages/changes.tsx +27 -41
  63. package/pages/settings.tsx +1 -0
  64. package/pages/slices.tsx +20 -8
  65. package/postcss.config.js +10 -0
  66. package/src/apiClient.ts +1 -22
  67. package/src/components/FieldSet/FieldSet.stories.tsx +20 -11
  68. package/src/components/RelativeTime/RelativeTime.stories.tsx +25 -0
  69. package/src/components/RelativeTime/RelativeTime.tsx +40 -0
  70. package/src/components/RelativeTime/index.ts +1 -0
  71. package/src/components/SideNav/SideNav.css.ts +1 -1
  72. package/src/components/SideNav/SideNav.tsx +9 -5
  73. package/src/components/SideNav/SideNavEnvironmentSelector.tsx +31 -11
  74. package/src/domain/__tests__/customType.test.ts +205 -19
  75. package/src/domain/customType.ts +132 -7
  76. package/src/domain/slice.ts +38 -0
  77. package/src/features/autoSave/AutoSaveStatusIndicator.tsx +4 -4
  78. package/src/features/customTypes/PageTypeOnboarding.tsx +21 -26
  79. package/src/features/customTypes/actions/convertCustomToPageType.ts +14 -10
  80. package/src/features/customTypes/actions/createCustomType.ts +69 -0
  81. package/src/features/customTypes/actions/deleteCustomType.ts +13 -3
  82. package/src/features/customTypes/actions/renameCustomType.ts +10 -4
  83. package/src/features/customTypes/customTypesBuilder/CustomTypeProvider.tsx +11 -10
  84. package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +5 -3
  85. package/src/features/customTypes/customTypesTable/CustomTypesTable.tsx +8 -8
  86. package/src/features/customTypes/customTypesTable/CustomTypesTablePage.tsx +18 -17
  87. package/src/features/environments/actions/setEnvironment.ts +4 -4
  88. package/src/features/settings/SettingsPage.tsx +47 -0
  89. package/src/features/settings/git/ConnectGitRepository.tsx +126 -0
  90. package/src/features/settings/git/ConnectGitRepositoryBlankSlate.tsx +33 -0
  91. package/src/features/settings/git/GitOwnerSelect.tsx +71 -0
  92. package/src/features/settings/git/GitProvider.ts +40 -0
  93. package/src/features/settings/git/GitProviderConnectButtons.tsx +63 -0
  94. package/src/features/settings/git/GitRepositoriesList.tsx +76 -0
  95. package/src/features/settings/git/GitRepositoriesSearch.tsx +69 -0
  96. package/src/features/settings/git/GitRepositoryConnectDialog.tsx +85 -0
  97. package/src/features/settings/git/GitRepositoryDisconnectDialog.tsx +60 -0
  98. package/src/features/settings/git/useGitIntegrationExperiment.ts +8 -0
  99. package/src/features/settings/git/useGitOwners.ts +12 -0
  100. package/src/features/settings/git/useGitRepos.ts +24 -0
  101. package/src/features/settings/git/useLinkedGitRepos.ts +41 -0
  102. package/src/features/settings/git/useWriteAPIToken.ts +23 -0
  103. package/src/features/slices/actions/createSlice.ts +5 -29
  104. package/src/features/slices/actions/deleteSlice.ts +33 -0
  105. package/src/features/slices/actions/renameSlice.ts +37 -0
  106. package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewSliceDialog.tsx +0 -1
  107. package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx +0 -1
  108. package/src/features/slices/convertLegacySlice/ConvertLegacySliceMergeWithIdenticalDialog.tsx +0 -1
  109. package/src/features/slices/sliceBuilder/SliceBuilderProvider.tsx +12 -10
  110. package/src/features/sync/AutoSyncProvider.tsx +252 -0
  111. package/src/features/sync/components/AutoSyncStatusIndicator.module.css +17 -0
  112. package/src/features/sync/components/AutoSyncStatusIndicator.module.css.d.ts +5 -0
  113. package/src/features/sync/components/AutoSyncStatusIndicator.tsx +58 -0
  114. package/src/features/sync/fetchUnSyncChanges.ts +40 -0
  115. package/src/features/sync/getUnSyncChanges.ts +144 -0
  116. package/src/features/sync/useUnSyncChanges.ts +32 -0
  117. package/src/hooks/useActionQueue.tsx +177 -0
  118. package/src/hooks/useAuthStatus.ts +12 -0
  119. package/src/hooks/useUser.ts +14 -0
  120. package/src/icons/SettingsIcon.tsx +19 -0
  121. package/src/icons/SyncFailed.tsx +30 -0
  122. package/src/icons/Synced.tsx +19 -0
  123. package/src/icons/Syncing.tsx +23 -0
  124. package/src/modules/availableCustomTypes/index.ts +29 -135
  125. package/src/modules/loading/types.ts +0 -5
  126. package/src/modules/modal/types.ts +0 -3
  127. package/src/modules/slices/index.ts +27 -193
  128. package/src/modules/slices/selector.ts +0 -14
  129. package/src/modules/useSliceMachineActions.ts +70 -89
  130. package/src/modules/userContext/index.ts +3 -3
  131. package/src/redux/saga.ts +0 -4
  132. package/test/__testutils__/index.tsx +8 -5
  133. package/test/src/modules/__fixtures__/serverState.ts +1 -2
  134. package/test/src/modules/availableCustomTypes/index.test.ts +2 -243
  135. package/test/src/modules/slices.test.ts +1 -267
  136. package/components/Navigation/ChangesListItem.tsx +0 -92
  137. package/components/Navigation/ChangesRightElement.tsx +0 -33
  138. package/out/_next/static/chunks/18539003-5cc559566b738915.js +0 -97
  139. package/out/_next/static/chunks/25-37d6fa7f064be04b.js +0 -1
  140. package/out/_next/static/chunks/318-ce7e74f18f2d5b22.js +0 -1
  141. package/out/_next/static/chunks/376-7e784d6069e01654.js +0 -8
  142. package/out/_next/static/chunks/727-3a3bc32518778317.js +0 -1
  143. package/out/_next/static/chunks/731-501990ebe6a71b32.js +0 -1
  144. package/out/_next/static/chunks/904-9a4c1264727ae89a.js +0 -1
  145. package/out/_next/static/chunks/pages/_app-cd9d4c76a4abc11a.js +0 -432
  146. package/out/_next/static/chunks/pages/changes-2a976f9efeb719aa.js +0 -1
  147. package/out/_next/static/chunks/pages/index-64cfb8b0948ba8ef.js +0 -1
  148. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-b2a9d773ce5d7739.js +0 -1
  149. package/out/_next/static/chunks/pages/slices-e9c70c082ca3e3f9.js +0 -1
  150. package/out/_next/static/css/200244e3e0463c39.css +0 -1
  151. package/out/_next/static/m6psnC5u1xT7Y6osWHKjp/_buildManifest.js +0 -1
  152. package/src/features/autoSave/useAutoSave.tsx +0 -177
  153. package/src/features/customTypes/__tests__/createCustomType.test.ts +0 -159
  154. package/src/features/customTypes/customTypesTable/createCustomType.ts +0 -107
  155. package/src/features/legacyState/actions/getLegacySliceMachineState.ts +0 -53
  156. package/src/features/legacyState/useLegacySliceMachineState.ts +0 -7
  157. package/src/hooks/useModelStatus.ts +0 -78
  158. package/src/hooks/useUnSyncChanges.ts +0 -88
  159. package/test/components/CreateCustomTypeModal.test.tsx +0 -73
  160. package/test/components/LoginModal.test.tsx +0 -67
  161. package/test/src/hooks/useModelStatus.test.ts +0 -115
  162. /package/out/_next/static/{m6psnC5u1xT7Y6osWHKjp → dS_xZnzzna6Y6uwcTgf90}/_ssgManifest.js +0 -0
  163. /package/src/features/{changes → sync}/actions/pushChanges.ts +0 -0
  164. /package/src/features/{changes → sync}/actions/trackPushChangesSuccess.ts +0 -0
@@ -1 +0,0 @@
1
- self.__BUILD_MANIFEST=function(s,c,a,e,t,i,f,b,n,u,d,h,l,k,j,p,g,o,r){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[a,j,p,"static/chunks/pages/index-64cfb8b0948ba8ef.js"],"/_error":["static/chunks/pages/_error-69b4f498bafdd188.js"],"/changelog":[s,e,"static/chunks/870-0c7a8a9622de78b7.js","static/chunks/pages/changelog-afd18276fe018b24.js"],"/changes":[s,t,"static/chunks/8eec4907-b712959d9f984b68.js",i,"static/chunks/918-5bb55fb464e34768.js",c,b,"static/css/37153180c3b0dd66.css","static/chunks/pages/changes-2a976f9efeb719aa.js"],"/custom-types":[a,j,p,"static/chunks/pages/custom-types-94b8f8dbf7727412.js"],"/custom-types/[customTypeId]":[s,n,u,d,h,e,f,i,l,g,c,a,k,o,r,"static/chunks/pages/custom-types/[customTypeId]-3f862ad6111a1fc0.js"],"/labs":["static/chunks/pages/labs-ee206005948f8e87.js"],"/page-types/[pageTypeId]":[s,n,u,d,h,e,f,i,l,g,c,a,k,o,r,"static/chunks/pages/page-types/[pageTypeId]-d1ffca11c42f2603.js"],"/slices":[s,t,f,c,b,"static/css/f8eb526e10bc2441.css","static/chunks/pages/slices-e9c70c082ca3e3f9.js"],"/slices/[lib]/[sliceName]/[variation]":[s,t,n,u,d,h,e,f,i,l,c,k,b,"static/css/b22c0750c14cc089.css","static/chunks/pages/slices/[lib]/[sliceName]/[variation]-b2a9d773ce5d7739.js"],"/slices/[lib]/[sliceName]/[variation]/simulator":[t,"static/chunks/72585f70-28b4d7d5384b3703.js","static/chunks/18539003-5cc559566b738915.js","static/chunks/376-7e784d6069e01654.js","static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-897ca93c114a1435.js"],sortedPages:["/","/_app","/_error","/changelog","/changes","/custom-types","/custom-types/[customTypeId]","/labs","/page-types/[pageTypeId]","/slices","/slices/[lib]/[sliceName]/[variation]","/slices/[lib]/[sliceName]/[variation]/simulator"]}}("static/chunks/59b4e022-7a3b5554b806349f.js","static/chunks/25-37d6fa7f064be04b.js","static/chunks/731-501990ebe6a71b32.js","static/chunks/183-4feb6bb3eddbc768.js","static/chunks/c8eae200-966ce352f7b5d2b9.js","static/chunks/543-f8766685f7f451e2.js","static/chunks/50-cfc2514205b86001.js","static/chunks/286-ed90373e9a469944.js","static/chunks/f36c6662-03bb5e9d9aa0b0aa.js","static/chunks/4c744e84-e3161d754618373f.js","static/chunks/065a3ddb-9a38ca0d60f0bf2f.js","static/chunks/1cc2734a-2c5b6c0367fcde86.js","static/chunks/696-b12edad30a3617e5.js","static/chunks/318-ce7e74f18f2d5b22.js","static/chunks/727-3a3bc32518778317.js","static/css/be1f49e49a5aa7eb.css","static/chunks/474-5a072e6fac61f703.js","static/chunks/904-9a4c1264727ae89a.js","static/css/72465cc1225f28a2.css"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -1,177 +0,0 @@
1
- import {
2
- useCallback,
3
- useState,
4
- useEffect,
5
- SetStateAction,
6
- Dispatch,
7
- useMemo,
8
- } from "react";
9
- import { uniqueId } from "lodash";
10
- import { toast } from "react-toastify";
11
- import { Box, Button, Text } from "@prismicio/editor-ui";
12
-
13
- export type AutoSaveStatus = "saving" | "saved" | "failed";
14
-
15
- type UseAutoSaveArgs = {
16
- autoSaveStatusDelay?: number;
17
- errorMessage?: string;
18
- retryDelay?: number;
19
- retryMessage?: string;
20
- };
21
-
22
- type UseAutoSaveReturnType = {
23
- autoSaveStatus: AutoSaveStatus;
24
- setNextSave: (nextSave: NextSave) => void;
25
- };
26
-
27
- type AutoSaveStack = {
28
- pendingSave: NextSave | undefined;
29
- nextSave: NextSave | undefined;
30
- };
31
-
32
- type NextSave = () => Promise<unknown>;
33
-
34
- export const useAutoSave = (
35
- args: UseAutoSaveArgs = {},
36
- ): UseAutoSaveReturnType => {
37
- const {
38
- autoSaveStatusDelay = 300,
39
- errorMessage = "An error happened while saving",
40
- retryDelay = 1000,
41
- retryMessage = "Retry",
42
- } = args;
43
-
44
- const [autoSaveStack, setAutoSaveStack] = useState<AutoSaveStack>({
45
- pendingSave: undefined,
46
- nextSave: undefined,
47
- });
48
- const [autoSaveStatusActual, setAutoSaveStatusActual] =
49
- useState<AutoSaveStatus>("saved");
50
- const [autoSaveStatusDelayed, setAutoSaveStatusDelayed] =
51
- useState<AutoSaveStatus>(autoSaveStatusActual);
52
-
53
- const setNextSave = useCallback((nextSave: NextSave) => {
54
- setAutoSaveStack((prevState) => ({
55
- ...prevState,
56
- nextSave,
57
- }));
58
- }, []);
59
-
60
- const executeSave = useCallback(
61
- async (nextSave?: NextSave) => {
62
- if (nextSave) {
63
- setAutoSaveStatusActual("saving");
64
-
65
- try {
66
- await nextSave();
67
-
68
- setAutoSaveStatusActual("saved");
69
- } catch (error) {
70
- setAutoSaveStatusActual("failed");
71
- console.error(errorMessage, error);
72
-
73
- toastError({
74
- errorMessage,
75
- retryDelay,
76
- retryMessage,
77
- setAutoSaveStatusActual,
78
- setAutoSaveStack,
79
- });
80
- }
81
- }
82
- },
83
- [errorMessage, retryDelay, retryMessage],
84
- );
85
-
86
- useEffect(() => {
87
- if (autoSaveStatusActual === "saved" && autoSaveStack.nextSave) {
88
- void executeSave(autoSaveStack.nextSave);
89
-
90
- setAutoSaveStack({
91
- pendingSave: autoSaveStack.nextSave,
92
- nextSave: undefined,
93
- });
94
- }
95
- }, [autoSaveStatusActual, autoSaveStack, executeSave]);
96
-
97
- useEffect(() => {
98
- if (autoSaveStatusActual === "saving") {
99
- setAutoSaveStatusDelayed("saving");
100
- } else {
101
- const delayedTimeout = setTimeout(() => {
102
- setAutoSaveStatusDelayed(autoSaveStatusActual);
103
- }, autoSaveStatusDelay);
104
-
105
- return () => {
106
- clearTimeout(delayedTimeout);
107
- };
108
- }
109
-
110
- return;
111
- }, [autoSaveStatusActual, autoSaveStatusDelay]);
112
-
113
- return useMemo(
114
- () => ({
115
- autoSaveStatus: autoSaveStatusDelayed,
116
- setNextSave,
117
- }),
118
- [autoSaveStatusDelayed, setNextSave],
119
- );
120
- };
121
-
122
- type ToastErrorArgs = {
123
- errorMessage: string;
124
- retryDelay: number;
125
- retryMessage: string;
126
- setAutoSaveStatusActual: Dispatch<SetStateAction<AutoSaveStatus>>;
127
- setAutoSaveStack: Dispatch<SetStateAction<AutoSaveStack>>;
128
- };
129
-
130
- function toastError(args: ToastErrorArgs) {
131
- const {
132
- errorMessage,
133
- retryDelay,
134
- retryMessage,
135
- setAutoSaveStatusActual,
136
- setAutoSaveStack,
137
- } = args;
138
- const toastId = uniqueId();
139
-
140
- toast.error(
141
- () => (
142
- <Box gap={8} alignItems="center">
143
- <Text color="grey1" variant="small">
144
- {errorMessage}
145
- </Text>
146
- <Button
147
- size="small"
148
- color="grey"
149
- onClick={() => {
150
- toast.dismiss(toastId);
151
-
152
- // Ensure saving is directly propagated before waiting for the retry
153
- setAutoSaveStatusActual("saving");
154
-
155
- setTimeout(() => {
156
- // By setting the status to saved, the save effect will be triggered
157
- // with the latest data to save.
158
- setAutoSaveStatusActual("saved");
159
- setAutoSaveStack((prevState) => ({
160
- nextSave: prevState.nextSave ?? prevState.pendingSave,
161
- pendingSave: undefined,
162
- }));
163
- }, retryDelay);
164
- }}
165
- >
166
- {retryMessage}
167
- </Button>
168
- </Box>
169
- ),
170
- {
171
- autoClose: false,
172
- closeOnClick: false,
173
- draggable: false,
174
- toastId,
175
- },
176
- );
177
- }
@@ -1,159 +0,0 @@
1
- import { describe, expect } from "vitest";
2
- import { createCustomType } from "@src/features/customTypes/customTypesTable/createCustomType";
3
-
4
- describe("createCustomType test suite", () => {
5
- it("should create a custom type with repeatable true", () => {
6
- expect(createCustomType("id", "lama", true, "custom"))
7
- .toMatchInlineSnapshot(`
8
- {
9
- "format": "custom",
10
- "id": "id",
11
- "json": {
12
- "Main": {
13
- "uid": {
14
- "config": {
15
- "label": "UID",
16
- },
17
- "type": "UID",
18
- },
19
- },
20
- },
21
- "label": "lama",
22
- "repeatable": true,
23
- "status": true,
24
- }
25
- `);
26
- });
27
-
28
- it("should create a custom type with repeatable false", () => {
29
- const result = createCustomType("id", "lama", false, "custom");
30
- expect(result.id).toBe("id");
31
- expect(result.label).toBe("lama");
32
- expect(result.format).toBe("custom");
33
- expect(result.json).toHaveProperty("Main");
34
- expect(result).toMatchInlineSnapshot(`
35
- {
36
- "format": "custom",
37
- "id": "id",
38
- "json": {
39
- "Main": {},
40
- },
41
- "label": "lama",
42
- "repeatable": false,
43
- "status": true,
44
- }
45
- `);
46
- });
47
-
48
- it("should create a page type with a slice zone", () => {
49
- const result = createCustomType("🥪", "label", true, "page");
50
- expect(result.format).toBe("page");
51
- expect(result.json).toHaveProperty("Main");
52
- expect(result.json.Main).toHaveProperty("slices");
53
- expect(result.json).toHaveProperty("SEO & Metadata");
54
- expect(result).toMatchInlineSnapshot(`
55
- {
56
- "format": "page",
57
- "id": "🥪",
58
- "json": {
59
- "Main": {
60
- "slices": {
61
- "config": {
62
- "choices": {},
63
- },
64
- "fieldset": "Slice Zone",
65
- "type": "Slices",
66
- },
67
- "uid": {
68
- "config": {
69
- "label": "UID",
70
- },
71
- "type": "UID",
72
- },
73
- },
74
- "SEO & Metadata": {
75
- "meta_description": {
76
- "config": {
77
- "label": "Meta Description",
78
- "placeholder": "A brief summary of the page",
79
- },
80
- "type": "Text",
81
- },
82
- "meta_image": {
83
- "config": {
84
- "constraint": {
85
- "height": 1260,
86
- "width": 2400,
87
- },
88
- "label": "Meta Image",
89
- "thumbnails": [],
90
- },
91
- "type": "Image",
92
- },
93
- "meta_title": {
94
- "config": {
95
- "label": "Meta Title",
96
- "placeholder": "A title of the page used for social media and search engines",
97
- },
98
- "type": "Text",
99
- },
100
- },
101
- },
102
- "label": "label",
103
- "repeatable": true,
104
- "status": true,
105
- }
106
- `);
107
- });
108
- });
109
-
110
- it("when non repeatable page type is should contain Main with a slice-zone, no uid, and a SEO tab", () => {
111
- const result = createCustomType("foo", "bar", false, "page");
112
- expect(result).toMatchInlineSnapshot(`
113
- {
114
- "format": "page",
115
- "id": "foo",
116
- "json": {
117
- "Main": {
118
- "slices": {
119
- "config": {
120
- "choices": {},
121
- },
122
- "fieldset": "Slice Zone",
123
- "type": "Slices",
124
- },
125
- },
126
- "SEO & Metadata": {
127
- "meta_description": {
128
- "config": {
129
- "label": "Meta Description",
130
- "placeholder": "A brief summary of the page",
131
- },
132
- "type": "Text",
133
- },
134
- "meta_image": {
135
- "config": {
136
- "constraint": {
137
- "height": 1260,
138
- "width": 2400,
139
- },
140
- "label": "Meta Image",
141
- "thumbnails": [],
142
- },
143
- "type": "Image",
144
- },
145
- "meta_title": {
146
- "config": {
147
- "label": "Meta Title",
148
- "placeholder": "A title of the page used for social media and search engines",
149
- },
150
- "type": "Text",
151
- },
152
- },
153
- },
154
- "label": "bar",
155
- "repeatable": false,
156
- "status": true,
157
- }
158
- `);
159
- });
@@ -1,107 +0,0 @@
1
- import { CustomType } from "@prismicio/types-internal/lib/customtypes";
2
- import type { CustomTypeFormat } from "@slicemachine/manager";
3
-
4
- export function createCustomType(
5
- id: string,
6
- label: string,
7
- repeatable: boolean,
8
- format: CustomTypeFormat,
9
- ): CustomType {
10
- const mainTab = makeMainTab(repeatable, format);
11
-
12
- return {
13
- id,
14
- label,
15
- format,
16
- repeatable,
17
- json: mainTab,
18
- status: true,
19
- };
20
- }
21
-
22
- function makeMainTab(
23
- repeatable: boolean,
24
- format: CustomTypeFormat,
25
- ): CustomType["json"] {
26
- if (repeatable === false && format === "page") {
27
- return { ...DEFAULT_MAIN_WITH_SLICE_ZONE, ...DEFAULT_SEO_TAB };
28
- }
29
-
30
- if (repeatable === false) {
31
- return DEFAULT_MAIN;
32
- }
33
-
34
- if (format === "page") {
35
- return {
36
- ...DEFAULT_MAIN_WITH_UID_AND_SLICE_ZONE,
37
- ...DEFAULT_SEO_TAB,
38
- };
39
- }
40
-
41
- return DEFAULT_MAIN_WITH_UID;
42
- }
43
-
44
- const DEFAULT_MAIN: CustomType["json"] = {
45
- Main: {},
46
- };
47
-
48
- const DEFAULT_MAIN_WITH_SLICE_ZONE: CustomType["json"] = {
49
- Main: {
50
- slices: {
51
- config: {
52
- choices: {},
53
- },
54
- fieldset: "Slice Zone",
55
- type: "Slices",
56
- },
57
- },
58
- };
59
-
60
- const DEFAULT_MAIN_WITH_UID: CustomType["json"] = {
61
- Main: {
62
- uid: {
63
- config: {
64
- label: "UID",
65
- },
66
- type: "UID",
67
- },
68
- },
69
- };
70
-
71
- const DEFAULT_MAIN_WITH_UID_AND_SLICE_ZONE: CustomType["json"] = {
72
- Main: {
73
- ...DEFAULT_MAIN_WITH_UID.Main,
74
- ...DEFAULT_MAIN_WITH_SLICE_ZONE.Main,
75
- },
76
- };
77
-
78
- const DEFAULT_SEO_TAB: CustomType["json"] = {
79
- "SEO & Metadata": {
80
- meta_description: {
81
- config: {
82
- label: "Meta Description",
83
- placeholder: "A brief summary of the page",
84
- },
85
- type: "Text",
86
- },
87
- meta_image: {
88
- config: {
89
- constraint: {
90
- height: 1260,
91
- width: 2400,
92
- },
93
- label: "Meta Image",
94
- thumbnails: [],
95
- },
96
- type: "Image",
97
- },
98
- meta_title: {
99
- config: {
100
- label: "Meta Title",
101
- placeholder:
102
- "A title of the page used for social media and search engines",
103
- },
104
- type: "Text",
105
- },
106
- },
107
- };
@@ -1,53 +0,0 @@
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
- }
@@ -1,7 +0,0 @@
1
- import { useRequest } from "@prismicio/editor-support/Suspense";
2
-
3
- import { getLegacySliceMachineState } from "./actions/getLegacySliceMachineState";
4
-
5
- export function useLegacySliceMachineState() {
6
- return useRequest(getLegacySliceMachineState, []);
7
- }
@@ -1,78 +0,0 @@
1
- import {
2
- computeModelStatus,
3
- ModelStatus,
4
- } from "@lib/models/common/ModelStatus";
5
- import { getAuthStatus } from "@src/modules/environment";
6
- import { AuthStatus } from "@src/modules/userContext/types";
7
- import { SliceMachineStoreType } from "@src/redux/type";
8
- import { useSelector } from "react-redux";
9
- import { useNetwork } from "./useNetwork";
10
- import {
11
- hasLocal,
12
- LocalOrRemoteCustomType,
13
- LocalOrRemoteModel,
14
- LocalOrRemoteSlice,
15
- } from "@lib/models/common/ModelData";
16
-
17
- // Slices and Custom Types needs to be separated as Ids are not unique amongst each others.
18
- export interface ModelStatusInformation {
19
- modelsStatuses: {
20
- slices: { [sliceId: string]: ModelStatus };
21
- customTypes: { [ctId: string]: ModelStatus };
22
- };
23
- authStatus: AuthStatus;
24
- isOnline: boolean;
25
- }
26
-
27
- function computeStatuses(
28
- models: LocalOrRemoteCustomType[],
29
- userHasAccessToModels: boolean,
30
- ): { [sliceId: string]: ModelStatus };
31
- function computeStatuses(
32
- models: LocalOrRemoteSlice[],
33
- userHasAccessToModels: boolean,
34
- ): { [sliceId: string]: ModelStatus };
35
- function computeStatuses(
36
- models: LocalOrRemoteModel[],
37
- userHasAccessToModels: boolean,
38
- ) {
39
- return models.reduce<{ [id: string]: ModelStatus }>(
40
- (acc, model) => {
41
- const { status } = computeModelStatus(model, userHasAccessToModels);
42
-
43
- return {
44
- ...acc,
45
- [hasLocal(model) ? model.local.id : model.remote.id]: status,
46
- };
47
- },
48
- {} as { [sliceId: string]: ModelStatus },
49
- );
50
- }
51
-
52
- export const useModelStatus = ({
53
- slices = [],
54
- customTypes = [],
55
- }: {
56
- slices?: LocalOrRemoteSlice[];
57
- customTypes?: LocalOrRemoteCustomType[];
58
- }): ModelStatusInformation => {
59
- const isOnline = useNetwork();
60
- const { authStatus } = useSelector((store: SliceMachineStoreType) => ({
61
- authStatus: getAuthStatus(store),
62
- }));
63
- const userHasAccessToModels =
64
- isOnline &&
65
- authStatus != AuthStatus.FORBIDDEN &&
66
- authStatus != AuthStatus.UNAUTHORIZED;
67
-
68
- const modelsStatuses = {
69
- slices: computeStatuses(slices, userHasAccessToModels),
70
- customTypes: computeStatuses(customTypes, userHasAccessToModels),
71
- };
72
-
73
- return {
74
- modelsStatuses,
75
- authStatus,
76
- isOnline,
77
- };
78
- };
@@ -1,88 +0,0 @@
1
- import { ComponentUI } from "@lib/models/common/ComponentUI";
2
- import { ModelStatus } from "@lib/models/common/ModelStatus";
3
- import { selectAllCustomTypes } from "@src/modules/availableCustomTypes";
4
- import { getFrontendSlices, getLibraries } from "@src/modules/slices";
5
- import { SliceMachineStoreType } from "@src/redux/type";
6
- import { useSelector } from "react-redux";
7
- import { ModelStatusInformation, useModelStatus } from "./useModelStatus";
8
- import {
9
- LocalOrRemoteCustomType,
10
- RemoteOnlySlice,
11
- getModelId,
12
- isRemoteOnly,
13
- } from "@lib/models/common/ModelData";
14
-
15
- export const unSyncStatuses = [
16
- ModelStatus.New,
17
- ModelStatus.Modified,
18
- ModelStatus.Deleted,
19
- ];
20
-
21
- export interface UnSyncChanges extends ModelStatusInformation {
22
- unSyncedSlices: ComponentUI[];
23
- unSyncedCustomTypes: LocalOrRemoteCustomType[];
24
- }
25
-
26
- // ComponentUI are manipulated on all the relevant pages
27
- // But the data is not available for remote only slices
28
- // which have been deleted locally
29
- // Should revisit this with the sync improvements
30
- const wrapDeletedSlice = (s: RemoteOnlySlice): ComponentUI => ({
31
- model: s.remote,
32
- screenshots: {},
33
- from: "",
34
- href: "",
35
- pathToSlice: "",
36
- fileName: "",
37
- extension: "",
38
- });
39
-
40
- export const useUnSyncChanges = (): UnSyncChanges => {
41
- const { customTypes, slices, libraries } = useSelector(
42
- (store: SliceMachineStoreType) => ({
43
- customTypes: selectAllCustomTypes(store),
44
- slices: getFrontendSlices(store),
45
- libraries: getLibraries(store),
46
- }),
47
- );
48
-
49
- const { modelsStatuses, authStatus, isOnline } = useModelStatus({
50
- slices,
51
- customTypes,
52
- });
53
-
54
- const localComponents: ComponentUI[] = libraries.flatMap(
55
- (lib) => lib.components,
56
- );
57
-
58
- const deletedComponents: ComponentUI[] = slices
59
- .filter(isRemoteOnly)
60
- .map(wrapDeletedSlice);
61
-
62
- const components: ComponentUI[] = localComponents
63
- .concat(deletedComponents)
64
- .sort((s1, s2) => (s1.model.name > s2.model.name ? 1 : -1));
65
-
66
- const unSyncedSlices = components.filter(
67
- (component) =>
68
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
69
- modelsStatuses.slices[component.model.id] &&
70
- unSyncStatuses.includes(modelsStatuses.slices[component.model.id]),
71
- );
72
- const unSyncedCustomTypes = customTypes.filter(
73
- (customType) =>
74
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
75
- modelsStatuses.customTypes[getModelId(customType)] &&
76
- unSyncStatuses.includes(
77
- modelsStatuses.customTypes[getModelId(customType)],
78
- ),
79
- );
80
-
81
- return {
82
- unSyncedSlices,
83
- unSyncedCustomTypes,
84
- modelsStatuses,
85
- authStatus,
86
- isOnline,
87
- };
88
- };