slice-machine-ui 1.23.2-alpha.xru-auto-sync-provider.3 → 1.23.2-beta.2

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 (117) hide show
  1. package/components/ChangesItems/ChangesItems.tsx +2 -6
  2. package/components/CustomTypeTable/changesPage.tsx +7 -12
  3. package/components/DeleteSliceModal/index.tsx +24 -37
  4. package/components/Forms/CreateCustomTypeModal/CreateCustomTypeModal.tsx +38 -65
  5. package/components/Forms/CreateSliceModal/CreateSliceModal.tsx +1 -3
  6. package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +2 -7
  7. package/components/Forms/RenameSliceModal/RenameSliceModal.tsx +21 -36
  8. package/components/LoginModal/index.tsx +2 -40
  9. package/components/Navigation/ChangesListItem.tsx +92 -0
  10. package/components/Navigation/ChangesRightElement.tsx +33 -0
  11. package/components/Navigation/Environment.tsx +4 -38
  12. package/components/Navigation/index.test.tsx +85 -5
  13. package/components/Navigation/index.tsx +8 -3
  14. package/lib/builders/SliceBuilder/index.tsx +3 -3
  15. package/lib/models/common/ModelStatus/index.ts +0 -25
  16. package/out/404.html +1 -1
  17. package/out/_next/static/{Fwm-rgKzl3GHiphGOBICh → HXkyCNwSfsIXY_W6wsobB}/_buildManifest.js +1 -1
  18. package/out/_next/static/chunks/25-37d6fa7f064be04b.js +1 -0
  19. package/out/_next/static/chunks/{318-454bf8a965950ade.js → 318-ce7e74f18f2d5b22.js} +1 -1
  20. package/out/_next/static/chunks/727-3a3bc32518778317.js +1 -0
  21. package/out/_next/static/chunks/731-501990ebe6a71b32.js +1 -0
  22. package/out/_next/static/chunks/904-9a4c1264727ae89a.js +1 -0
  23. package/out/_next/static/chunks/pages/{_app-49689700be9746a4.js → _app-a6fbbdc935e999c8.js} +23 -23
  24. package/out/_next/static/chunks/pages/{changelog-e7fec5abbaa7fd76.js → changelog-afd18276fe018b24.js} +1 -1
  25. package/out/_next/static/chunks/pages/changes-2a976f9efeb719aa.js +1 -0
  26. package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-97ab3b90b85d645d.js → [customTypeId]-3f862ad6111a1fc0.js} +1 -1
  27. package/out/_next/static/chunks/pages/{custom-types-3c8e721ec6802127.js → custom-types-94b8f8dbf7727412.js} +1 -1
  28. package/out/_next/static/chunks/pages/index-64cfb8b0948ba8ef.js +1 -0
  29. package/out/_next/static/chunks/pages/{labs-6e4db3f376f06dd9.js → labs-ee206005948f8e87.js} +1 -1
  30. package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-84a22c5e480d3fa9.js → [pageTypeId]-d1ffca11c42f2603.js} +1 -1
  31. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/{simulator-154af07027964d85.js → simulator-897ca93c114a1435.js} +1 -1
  32. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-b2a9d773ce5d7739.js +1 -0
  33. package/out/_next/static/chunks/pages/slices-e9c70c082ca3e3f9.js +1 -0
  34. package/out/_next/static/css/{0a8858de76498e62.css → 200244e3e0463c39.css} +1 -1
  35. package/out/changelog.html +1 -1
  36. package/out/changes.html +1 -1
  37. package/out/custom-types/[customTypeId].html +1 -1
  38. package/out/custom-types.html +1 -1
  39. package/out/index.html +1 -1
  40. package/out/labs.html +1 -1
  41. package/out/page-types/[pageTypeId].html +1 -1
  42. package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  43. package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
  44. package/out/slices.html +1 -1
  45. package/package.json +3 -3
  46. package/pages/_app.tsx +32 -34
  47. package/pages/changes.tsx +41 -27
  48. package/pages/slices.tsx +8 -20
  49. package/src/apiClient.ts +22 -1
  50. package/src/components/FieldSet/FieldSet.stories.tsx +36 -3
  51. package/src/components/SideNav/SideNav.css.ts +1 -1
  52. package/src/components/SideNav/SideNav.tsx +5 -9
  53. package/src/components/SideNav/SideNavEnvironmentSelector.tsx +1 -7
  54. package/src/domain/__tests__/customType.test.ts +0 -179
  55. package/src/domain/customType.ts +2 -110
  56. package/src/domain/slice.ts +0 -38
  57. package/src/features/autoSave/AutoSaveStatusIndicator.tsx +4 -4
  58. package/src/features/autoSave/useAutoSave.tsx +177 -0
  59. package/src/features/customTypes/PageTypeOnboarding.tsx +26 -21
  60. package/src/features/customTypes/__tests__/createCustomType.test.ts +159 -0
  61. package/src/features/customTypes/actions/convertCustomToPageType.ts +10 -14
  62. package/src/features/customTypes/actions/deleteCustomType.ts +3 -13
  63. package/src/features/customTypes/actions/renameCustomType.ts +4 -10
  64. package/src/features/customTypes/customTypesBuilder/CustomTypeProvider.tsx +10 -11
  65. package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +3 -5
  66. package/src/features/customTypes/customTypesTable/CustomTypesTable.tsx +8 -8
  67. package/src/features/customTypes/customTypesTable/CustomTypesTablePage.tsx +17 -18
  68. package/src/features/customTypes/customTypesTable/createCustomType.ts +107 -0
  69. package/src/features/environments/actions/setEnvironment.ts +3 -3
  70. package/src/features/legacyState/actions/getLegacySliceMachineState.ts +53 -0
  71. package/src/features/legacyState/useLegacySliceMachineState.ts +7 -0
  72. package/src/features/slices/actions/createSlice.ts +29 -5
  73. package/src/features/slices/sliceBuilder/SliceBuilderProvider.tsx +10 -12
  74. package/src/hooks/useModelStatus.ts +78 -0
  75. package/src/hooks/useUnSyncChanges.ts +88 -0
  76. package/src/modules/availableCustomTypes/index.ts +135 -29
  77. package/src/modules/loading/types.ts +5 -0
  78. package/src/modules/modal/types.ts +3 -0
  79. package/src/modules/slices/index.ts +193 -27
  80. package/src/modules/slices/selector.ts +14 -0
  81. package/src/modules/useSliceMachineActions.ts +89 -70
  82. package/src/modules/userContext/index.ts +3 -3
  83. package/src/redux/saga.ts +4 -0
  84. package/test/__testutils__/index.tsx +5 -8
  85. package/test/components/CreateCustomTypeModal.test.tsx +73 -0
  86. package/test/components/LoginModal.test.tsx +67 -0
  87. package/test/src/hooks/useModelStatus.test.ts +115 -0
  88. package/test/src/modules/availableCustomTypes/index.test.ts +243 -2
  89. package/test/src/modules/slices.test.ts +267 -1
  90. package/components/Navigation/ChangesItem.tsx +0 -117
  91. package/out/_next/static/chunks/25-3aa4d4b24167d340.js +0 -1
  92. package/out/_next/static/chunks/727-c831123e1c86b720.js +0 -1
  93. package/out/_next/static/chunks/799-23b4576fcfc3120b.js +0 -1
  94. package/out/_next/static/chunks/904-01fd75f7fda35678.js +0 -1
  95. package/out/_next/static/chunks/pages/changes-62c82c4a394f2205.js +0 -1
  96. package/out/_next/static/chunks/pages/index-cf93d16e9c63b6db.js +0 -1
  97. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-d19b12efd6e632f9.js +0 -1
  98. package/out/_next/static/chunks/pages/slices-cdb42209ce1f0b88.js +0 -1
  99. package/src/features/customTypes/actions/createCustomType.ts +0 -69
  100. package/src/features/slices/actions/deleteSlice.ts +0 -33
  101. package/src/features/slices/actions/renameSlice.ts +0 -37
  102. package/src/features/sync/AutoSyncProvider.tsx +0 -243
  103. package/src/features/sync/components/AutoSyncStatusIndicator.module.css +0 -19
  104. package/src/features/sync/components/AutoSyncStatusIndicator.module.css.d.ts +0 -5
  105. package/src/features/sync/components/AutoSyncStatusIndicator.tsx +0 -59
  106. package/src/features/sync/fetchUnSyncChanges.ts +0 -40
  107. package/src/features/sync/getUnSyncChanges.ts +0 -144
  108. package/src/features/sync/useUnSyncChanges.ts +0 -32
  109. package/src/hooks/useActionQueue.tsx +0 -177
  110. package/src/hooks/useAuthStatus.ts +0 -12
  111. package/src/hooks/useOnMountEffect.ts +0 -6
  112. package/src/icons/SyncFailed.tsx +0 -30
  113. package/src/icons/Synced.tsx +0 -19
  114. package/src/icons/Syncing.tsx +0 -23
  115. /package/out/_next/static/{Fwm-rgKzl3GHiphGOBICh → HXkyCNwSfsIXY_W6wsobB}/_ssgManifest.js +0 -0
  116. /package/src/features/{sync → changes}/actions/pushChanges.ts +0 -0
  117. /package/src/features/{sync → changes}/actions/trackPushChangesSuccess.ts +0 -0
@@ -6,23 +6,19 @@ import { ChangesSectionHeader } from "@components/ChangesSectionHeader";
6
6
  import { CustomTypeTable } from "@components/CustomTypeTable/changesPage";
7
7
  import Grid from "@components/Grid";
8
8
  import { ComponentUI } from "@lib/models/common/ComponentUI";
9
+ import { ModelStatusInformation } from "@src/hooks/useModelStatus";
9
10
  import ScreenshotChangesModal from "@components/ScreenshotChangesModal";
10
11
  import { countMissingScreenshots } from "@src/domain/slice";
11
12
  import { useScreenshotChangesModal } from "@src/hooks/useScreenshotChangesModal";
12
13
  import { ModelStatus } from "@lib/models/common/ModelStatus";
13
14
  import { LocalOrRemoteCustomType } from "@lib/models/common/ModelData";
14
15
  import { SharedSliceCard } from "@src/features/slices/sliceCards/SharedSliceCard";
15
- import { AuthStatus } from "@src/modules/userContext/types";
16
- import { ModelsStatuses } from "@src/features/sync/getUnSyncChanges";
17
16
 
18
17
  import { DevCollaborationExperiment } from "./DevCollaborationExperiment";
19
18
 
20
- interface ChangesItemsProps {
19
+ interface ChangesItemsProps extends ModelStatusInformation {
21
20
  unSyncedCustomTypes: LocalOrRemoteCustomType[];
22
21
  unSyncedSlices: ComponentUI[];
23
- modelsStatuses: ModelsStatuses;
24
- authStatus: AuthStatus;
25
- isOnline: boolean;
26
22
  }
27
23
 
28
24
  export const ChangesItems: React.FC<ChangesItemsProps> = ({
@@ -1,6 +1,7 @@
1
1
  import Link from "next/link";
2
2
  import React from "react";
3
3
  import { Box, Text } from "theme-ui";
4
+ import { ModelStatusInformation } from "@src/hooks/useModelStatus";
4
5
  import { CustomTypeSM } from "@lib/models/common/CustomType";
5
6
  import { ModelStatus } from "@lib/models/common/ModelStatus";
6
7
  import {
@@ -9,26 +10,18 @@ import {
9
10
  } from "@lib/models/common/ModelData";
10
11
  import { StatusBadge } from "@src/features/changes/StatusBadge";
11
12
  import { CUSTOM_TYPES_CONFIG } from "@src/features/customTypes/customTypesConfig";
12
- import { AuthStatus } from "@src/modules/userContext/types";
13
- import { ModelsStatuses } from "@src/features/sync/getUnSyncChanges";
14
13
 
15
- interface CustomTypeTableProps {
14
+ interface CustomTypeTableProps extends ModelStatusInformation {
16
15
  customTypes: LocalOrRemoteCustomType[];
17
- modelsStatuses: ModelsStatuses;
18
- authStatus: AuthStatus;
19
- isOnline: boolean;
20
16
  }
21
17
 
22
18
  const firstColumnWidth = "40%";
23
19
  const secondColumnWidth = "40%";
24
20
  const thirdColumnWidth = "20%";
25
21
 
26
- const CustomTypeChangeRow: React.FC<{
27
- ct: CustomTypeSM;
28
- status: ModelStatus;
29
- authStatus: AuthStatus;
30
- isOnline: boolean;
31
- }> = ({ ct, status, authStatus, isOnline }) => {
22
+ const CustomTypeChangeRow: React.FC<
23
+ { ct: CustomTypeSM; status: ModelStatus } & ModelStatusInformation
24
+ > = ({ ct, status, authStatus, isOnline }) => {
32
25
  return (
33
26
  <>
34
27
  <Box as={"td"} style={{ width: firstColumnWidth }}>
@@ -87,6 +80,7 @@ export const CustomTypeTable: React.FC<CustomTypeTableProps> = ({
87
80
  status={modelsStatuses.customTypes[customType.local.id]}
88
81
  authStatus={authStatus}
89
82
  isOnline={isOnline}
83
+ modelsStatuses={modelsStatuses}
90
84
  key={customType.local.id}
91
85
  />
92
86
  </tr>
@@ -103,6 +97,7 @@ export const CustomTypeTable: React.FC<CustomTypeTableProps> = ({
103
97
  status={modelsStatuses.customTypes[customType.remote.id]}
104
98
  authStatus={authStatus}
105
99
  isOnline={isOnline}
100
+ modelsStatuses={modelsStatuses}
106
101
  key={customType.remote.id}
107
102
  />
108
103
  </tr>
@@ -1,57 +1,46 @@
1
- import { useState } from "react";
2
- import { MdOutlineDelete } from "react-icons/md";
3
- import { Close, Flex, Heading, Paragraph, Text, useThemeUI } from "theme-ui";
4
-
5
1
  import SliceMachineModal from "@components/SliceMachineModal";
2
+ import { useSelector } from "react-redux";
3
+ import { SliceMachineStoreType } from "@src/redux/type";
4
+ import { isModalOpen } from "@src/modules/modal";
5
+ import { ModalKeysEnum } from "@src/modules/modal/types";
6
6
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
7
+ import { Close, Flex, Heading, Paragraph, Text, useThemeUI } from "theme-ui";
7
8
  import Card from "@components/Card";
9
+ import { MdOutlineDelete } from "react-icons/md";
8
10
  import { Button } from "@components/Button";
9
- import { deleteSlice } from "@src/features/slices/actions/deleteSlice";
10
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
11
+ import { LoadingKeysEnum } from "@src/modules/loading/types";
12
+ import { isLoading } from "@src/modules/loading";
11
13
 
12
14
  type DeleteSliceModalProps = {
13
- isOpen: boolean;
14
- libName: string;
15
15
  sliceId: string;
16
16
  sliceName: string;
17
- onClose: () => void;
17
+ libName: string;
18
18
  };
19
19
 
20
20
  export const DeleteSliceModal: React.FunctionComponent<
21
21
  DeleteSliceModalProps
22
- > = ({ sliceId, sliceName, libName, isOpen, onClose }) => {
23
- const [isDeleting, setIsDeleting] = useState(false);
24
- const { deleteSliceSuccess } = useSliceMachineActions();
25
- const { syncChanges } = useAutoSync();
26
- const { theme } = useThemeUI();
27
-
28
- const onDelete = async () => {
29
- setIsDeleting(true);
22
+ > = ({ sliceId, sliceName, libName }) => {
23
+ const { isSliceModalOpen, isDeletingSlice } = useSelector(
24
+ (store: SliceMachineStoreType) => ({
25
+ isSliceModalOpen: isModalOpen(store, ModalKeysEnum.DELETE_SLICE),
26
+ isDeletingSlice: isLoading(store, LoadingKeysEnum.DELETE_SLICE),
27
+ }),
28
+ );
30
29
 
31
- await deleteSlice({
32
- sliceID: sliceId,
33
- sliceName,
34
- libraryID: libName,
35
- onSuccess: () => {
36
- deleteSliceSuccess(sliceId, libName);
37
- syncChanges();
38
- },
39
- });
30
+ const { closeModals, deleteSlice } = useSliceMachineActions();
40
31
 
41
- onClose();
42
- setIsDeleting(false);
43
- };
32
+ const { theme } = useThemeUI();
44
33
 
45
34
  return (
46
35
  <SliceMachineModal
47
- isOpen={isOpen}
36
+ isOpen={isSliceModalOpen}
48
37
  shouldCloseOnOverlayClick={true}
49
38
  style={{
50
39
  content: {
51
40
  maxWidth: 612,
52
41
  },
53
42
  }}
54
- onRequestClose={onClose}
43
+ onRequestClose={closeModals}
55
44
  >
56
45
  <Card
57
46
  bodySx={{
@@ -90,7 +79,7 @@ export const DeleteSliceModal: React.FunctionComponent<
90
79
  Delete Slice
91
80
  </Heading>
92
81
  </Flex>
93
- <Close type="button" onClick={onClose} />
82
+ <Close type="button" onClick={closeModals} />
94
83
  </Flex>
95
84
  )}
96
85
  Footer={() => (
@@ -107,7 +96,7 @@ export const DeleteSliceModal: React.FunctionComponent<
107
96
  <Button
108
97
  label="Cancel"
109
98
  variant="secondary"
110
- onClick={onClose}
99
+ onClick={() => closeModals()}
111
100
  sx={{
112
101
  mr: "10px",
113
102
  fontWeight: "bold",
@@ -118,11 +107,9 @@ export const DeleteSliceModal: React.FunctionComponent<
118
107
  <Button
119
108
  label="Delete"
120
109
  variant="danger"
121
- isLoading={isDeleting}
110
+ isLoading={isDeletingSlice}
122
111
  sx={{ minHeight: 39, minWidth: 78 }}
123
- onClick={() => {
124
- void onDelete();
125
- }}
112
+ onClick={() => deleteSlice(sliceId, sliceName, libName)}
126
113
  />
127
114
  </Flex>
128
115
  )}
@@ -2,29 +2,25 @@ import { SetStateAction, useState } from "react";
2
2
  import { Box } from "theme-ui";
3
3
  import { FormikErrors } from "formik";
4
4
  import { useSelector } from "react-redux";
5
- import { useRouter } from "next/router";
6
5
 
7
6
  import ModalFormCard from "@components/ModalFormCard";
7
+ import { InputBox } from "../components/InputBox";
8
+ import { SelectRepeatable } from "../components/SelectRepeatable";
8
9
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
9
10
  import { SliceMachineStoreType } from "@src/redux/type";
10
11
  import {
11
12
  selectAllCustomTypeIds,
12
13
  selectAllCustomTypeLabels,
13
14
  } from "@src/modules/availableCustomTypes";
15
+ import { isModalOpen } from "@src/modules/modal";
16
+ import { ModalKeysEnum } from "@src/modules/modal/types";
17
+ import { isLoading } from "@src/modules/loading";
18
+ import { LoadingKeysEnum } from "@src/modules/loading/types";
19
+ import { telemetry } from "@src/apiClient";
14
20
  import { slugify } from "@lib/utils/str";
15
21
  import { API_ID_REGEX } from "@lib/consts";
16
22
  import type { CustomTypeFormat } from "@slicemachine/manager";
17
23
  import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
18
- import {
19
- CustomTypeOrigin,
20
- createCustomType,
21
- } from "@src/features/customTypes/actions/createCustomType";
22
- import { CUSTOM_TYPES_CONFIG } from "@src/features/customTypes/customTypesConfig";
23
- import { getFormat } from "@src/domain/customType";
24
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
25
-
26
- import { InputBox } from "../components/InputBox";
27
- import { SelectRepeatable } from "../components/SelectRepeatable";
28
24
 
29
25
  interface FormValues {
30
26
  id: string;
@@ -34,67 +30,46 @@ interface FormValues {
34
30
 
35
31
  type CreateCustomTypeModalProps = {
36
32
  format: CustomTypeFormat;
37
- isCreating: boolean;
38
- isOpen: boolean;
39
- origin?: CustomTypeOrigin;
40
- onCreateChange: (isCreating: boolean) => void;
41
- onOpenChange: (isOpen: boolean) => void;
33
+ origin?: "onboarding" | "table";
42
34
  };
43
35
 
44
36
  export const CreateCustomTypeModal: React.FC<CreateCustomTypeModalProps> = ({
45
37
  format,
46
- isCreating,
47
- isOpen,
48
38
  origin = "table",
49
- onCreateChange,
50
- onOpenChange,
51
39
  }) => {
52
- const { createCustomTypeSuccess } = useSliceMachineActions();
53
-
54
- const { customTypeIds, customTypeLabels } = useSelector(
55
- (store: SliceMachineStoreType) => ({
56
- customTypeIds: selectAllCustomTypeIds(store),
57
- customTypeLabels: selectAllCustomTypeLabels(store),
58
- }),
59
- );
40
+ const { createCustomType, closeModals } = useSliceMachineActions();
41
+
42
+ const {
43
+ customTypeIds,
44
+ isCreateCustomTypeModalOpen,
45
+ isCreatingCustomType,
46
+ customTypeLabels,
47
+ } = useSelector((store: SliceMachineStoreType) => ({
48
+ customTypeIds: selectAllCustomTypeIds(store),
49
+ customTypeLabels: selectAllCustomTypeLabels(store),
50
+ isCreateCustomTypeModalOpen: isModalOpen(
51
+ store,
52
+ ModalKeysEnum.CREATE_CUSTOM_TYPE,
53
+ ),
54
+ isCreatingCustomType: isLoading(store, LoadingKeysEnum.CREATE_CUSTOM_TYPE),
55
+ }));
60
56
  const customTypesMessages = CUSTOM_TYPES_MESSAGES[format];
61
57
  const [isIdFieldPristine, setIsIdFieldPristine] = useState(true);
62
- const { syncChanges } = useAutoSync();
63
- const router = useRouter();
64
58
 
65
- const onSubmit = async ({ id, label, repeatable }: FormValues) => {
66
- onCreateChange(true);
59
+ const createCustomTypeAndTrack = ({ id, label, repeatable }: FormValues) => {
60
+ const name = label || id;
67
61
 
68
- await createCustomType({
69
- format,
62
+ void telemetry.track({
63
+ event: "custom-type:created",
70
64
  id,
71
- label,
65
+ name,
66
+ format,
67
+ type: repeatable ? "repeatable" : "single",
72
68
  origin,
73
- repeatable,
74
- onSuccess: async (newCustomType) => {
75
- createCustomTypeSuccess(newCustomType);
76
-
77
- const format = getFormat(newCustomType);
78
- const customTypesConfig = CUSTOM_TYPES_CONFIG[format];
79
-
80
- setIsIdFieldPristine(true);
81
-
82
- await router.push({
83
- pathname: customTypesConfig.getBuilderPagePathname(id),
84
- query:
85
- newCustomType.format === "page"
86
- ? {
87
- newPageType: true,
88
- }
89
- : undefined,
90
- });
91
-
92
- syncChanges();
93
- },
94
69
  });
95
-
96
- onCreateChange(false);
97
- onOpenChange(false);
70
+ createCustomType(id, name, repeatable, format);
71
+ closeModals();
72
+ setIsIdFieldPristine(true);
98
73
  };
99
74
 
100
75
  const handleLabelChange = (
@@ -131,18 +106,16 @@ export const CreateCustomTypeModal: React.FC<CreateCustomTypeModalProps> = ({
131
106
  return (
132
107
  <ModalFormCard
133
108
  dataCy="create-ct-modal"
134
- isOpen={isOpen}
109
+ isOpen={isCreateCustomTypeModalOpen}
135
110
  widthInPx="530px"
136
111
  formId="create-custom-type"
137
112
  buttonLabel={"Create"}
138
113
  close={() => {
139
- onOpenChange(false);
114
+ closeModals();
140
115
  setIsIdFieldPristine(true);
141
116
  }}
142
- onSubmit={(values) => {
143
- void onSubmit(values);
144
- }}
145
- isLoading={isCreating}
117
+ onSubmit={createCustomTypeAndTrack}
118
+ isLoading={isCreatingCustomType}
146
119
  initialValues={{
147
120
  repeatable: true,
148
121
  id: "",
@@ -9,7 +9,6 @@ import ModalFormCard from "@components/ModalFormCard";
9
9
  import { createSlice } from "@src/features/slices/actions/createSlice";
10
10
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
11
11
  import { getState } from "@src/apiClient";
12
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
13
12
 
14
13
  import { validateSliceModalValues } from "../formsValidator";
15
14
  import { InputBox } from "../components/InputBox";
@@ -31,7 +30,6 @@ export const CreateSliceModal: FC<CreateSliceModalProps> = ({
31
30
  }) => {
32
31
  const { createSliceSuccess } = useSliceMachineActions();
33
32
  const [isCreatingSlice, setIsCreatingSlice] = useState(false);
34
- const { syncChanges } = useAutoSync();
35
33
 
36
34
  const onSubmit = async (values: FormValues) => {
37
35
  const sliceName = values.sliceName;
@@ -47,8 +45,8 @@ export const CreateSliceModal: FC<CreateSliceModalProps> = ({
47
45
  const serverState = await getState();
48
46
  // Update Redux store
49
47
  createSliceSuccess(serverState.libraries);
48
+
50
49
  onSuccess(newSlice, libraryName);
51
- syncChanges();
52
50
  },
53
51
  });
54
52
  };
@@ -13,7 +13,6 @@ import { CustomTypeFormat } from "@slicemachine/manager";
13
13
  import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
14
14
 
15
15
  import { renameCustomType } from "@src/features/customTypes/actions/renameCustomType";
16
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
17
16
 
18
17
  interface RenameCustomTypeModalProps {
19
18
  isChangesLocal: boolean;
@@ -32,8 +31,7 @@ export const RenameCustomTypeModal: React.FC<RenameCustomTypeModalProps> = ({
32
31
  }) => {
33
32
  const customTypeName = customType?.label ?? "";
34
33
  const customTypeId = customType?.id ?? "";
35
- const { renameCustomTypeSuccess } = useSliceMachineActions();
36
- const { syncChanges } = useAutoSync();
34
+ const { renameAvailableCustomTypeSuccess } = useSliceMachineActions();
37
35
 
38
36
  const [isRenaming, setIsRenaming] = useState(false);
39
37
 
@@ -48,10 +46,7 @@ export const RenameCustomTypeModal: React.FC<RenameCustomTypeModalProps> = ({
48
46
  await renameCustomType({
49
47
  model: customType,
50
48
  newLabel: values.customTypeName,
51
- onSuccess: (renamedCustomType) => {
52
- renameCustomTypeSuccess(renamedCustomType);
53
- syncChanges();
54
- },
49
+ onSuccess: renameAvailableCustomTypeSuccess,
55
50
  });
56
51
  }
57
52
  setIsRenaming(false);
@@ -1,65 +1,50 @@
1
1
  import { Box } from "theme-ui";
2
- import { useSelector } from "react-redux";
3
-
4
2
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
3
+ import ModalFormCard from "../../ModalFormCard";
4
+ import { InputBox } from "../components/InputBox";
5
+ import { useSelector } from "react-redux";
5
6
  import { SliceMachineStoreType } from "@src/redux/type";
7
+ import { isModalOpen } from "@src/modules/modal";
8
+ import { ModalKeysEnum } from "@src/modules/modal/types";
6
9
  import { getLibraries, getRemoteSlices } from "@src/modules/slices";
7
- import { ComponentUI } from "@lib/models/common/ComponentUI";
8
- import { renameSlice } from "@src/features/slices/actions/renameSlice";
9
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
10
-
11
- import { InputBox } from "../components/InputBox";
12
- import ModalFormCard from "../../ModalFormCard";
13
10
  import { SliceModalValues } from "../formsTypes";
14
11
  import { validateSliceModalValues } from "../formsValidator";
15
12
 
16
13
  interface RenameSliceModalProps {
17
- isOpen: boolean;
18
- slice?: ComponentUI;
19
- onClose: () => void;
14
+ sliceName: string;
15
+ sliceId: string;
16
+ libName: string;
20
17
  }
21
18
 
22
19
  export const RenameSliceModal: React.FC<RenameSliceModalProps> = ({
23
- slice,
24
- isOpen,
25
- onClose,
20
+ sliceName,
21
+ sliceId,
22
+ libName,
26
23
  }) => {
27
- const { renameSliceSuccess } = useSliceMachineActions();
28
- const { syncChanges } = useAutoSync();
29
- const { localLibs, remoteLibs } = useSelector(
24
+ const { renameSlice, closeModals } = useSliceMachineActions();
25
+ const { isRenameSliceModalOpen, localLibs, remoteLibs } = useSelector(
30
26
  (store: SliceMachineStoreType) => ({
27
+ isRenameSliceModalOpen: isModalOpen(store, ModalKeysEnum.RENAME_SLICE),
31
28
  localLibs: getLibraries(store),
32
29
  remoteLibs: getRemoteSlices(store),
33
30
  }),
34
31
  );
35
- const initialSliceName = slice?.model.name ?? "";
36
-
37
- const handleOnSubmit = async (values: SliceModalValues) => {
38
- if (slice) {
39
- await renameSlice({
40
- slice,
41
- newSliceName: values.sliceName,
42
- onSuccess: (renamedSlice) => {
43
- renameSliceSuccess(renamedSlice.from, renamedSlice.model);
44
- syncChanges();
45
- },
46
- });
47
32
 
48
- onClose();
49
- }
33
+ const handleOnSubmit = (values: SliceModalValues) => {
34
+ renameSlice(libName, sliceId, values.sliceName);
50
35
  };
51
36
 
52
37
  return (
53
38
  <ModalFormCard<SliceModalValues>
54
39
  dataCy="rename-slice-modal"
55
- isOpen={isOpen}
40
+ isOpen={isRenameSliceModalOpen}
56
41
  widthInPx="530px"
57
- formId={`rename-slice-modal-${slice?.model.id ?? ""}`}
58
- close={onClose}
42
+ formId={`rename-slice-modal-${sliceId}`}
43
+ close={closeModals}
59
44
  buttonLabel="Rename"
60
- onSubmit={(values) => void handleOnSubmit(values)}
45
+ onSubmit={handleOnSubmit}
61
46
  initialValues={{
62
- sliceName: initialSliceName,
47
+ sliceName: sliceName,
63
48
  }}
64
49
  content={{
65
50
  title: "Rename a slice",
@@ -11,7 +11,7 @@ import {
11
11
  Text,
12
12
  } from "theme-ui";
13
13
  import SliceMachineModal from "@components/SliceMachineModal";
14
- import { checkAuthStatus, getState, startAuth } from "@src/apiClient";
14
+ import { checkAuthStatus, startAuth } from "@src/apiClient";
15
15
  import { buildEndpoints } from "@lib/prismic/endpoints";
16
16
  import { startPolling } from "@lib/utils/poll";
17
17
  import { CheckAuthStatusResponse } from "@models/common/Auth";
@@ -25,12 +25,6 @@ import { getEnvironment } from "@src/modules/environment";
25
25
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
26
26
  import preferWroomBase from "@lib/utils/preferWroomBase";
27
27
  import { ToasterType } from "@src/modules/toaster";
28
- import { getUnSyncedChanges } from "@src/features/sync/getUnSyncChanges";
29
- import { normalizeFrontendCustomTypes } from "@lib/models/common/normalizers/customType";
30
- import { normalizeFrontendSlices } from "@lib/models/common/normalizers/slices";
31
- import { AuthStatus } from "@src/modules/userContext/types";
32
- import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
33
- import { getActiveEnvironment } from "@src/features/environments/actions/getActiveEnvironment";
34
28
 
35
29
  interface ValidAuthStatus extends CheckAuthStatusResponse {
36
30
  status: "ok";
@@ -48,7 +42,7 @@ const LoginModal: React.FunctionComponent = () => {
48
42
  env: getEnvironment(store),
49
43
  }),
50
44
  );
51
- const { syncChanges } = useAutoSync();
45
+
52
46
  const { closeModals, startLoadingLogin, stopLoadingLogin, openToaster } =
53
47
  useSliceMachineActions();
54
48
 
@@ -78,38 +72,6 @@ const LoginModal: React.FunctionComponent = () => {
78
72
  openToaster("Logged in", ToasterType.SUCCESS);
79
73
  stopLoadingLogin();
80
74
  closeModals();
81
-
82
- const serverState = await getState();
83
- const slices = normalizeFrontendSlices(
84
- serverState.libraries,
85
- serverState.remoteSlices,
86
- );
87
- const customTypes = Object.values(
88
- normalizeFrontendCustomTypes(
89
- serverState.customTypes,
90
- serverState.remoteCustomTypes,
91
- ),
92
- );
93
- const { changedCustomTypes, changedSlices } = getUnSyncedChanges({
94
- authStatus: AuthStatus.AUTHORIZED,
95
- customTypes,
96
- isOnline: true,
97
- libraries: serverState.libraries,
98
- slices,
99
- });
100
- const { activeEnvironment } = await getActiveEnvironment();
101
-
102
- if (
103
- activeEnvironment?.kind === "dev" &&
104
- (changedCustomTypes.length > 0 || changedSlices.length > 0)
105
- ) {
106
- syncChanges({
107
- environment: activeEnvironment,
108
- loggedIn: true,
109
- changedCustomTypes,
110
- changedSlices,
111
- });
112
- }
113
75
  } catch (e) {
114
76
  stopLoadingLogin();
115
77
  openToaster("Login failed", ToasterType.ERROR);
@@ -0,0 +1,92 @@
1
+ import { type FC, useState } from "react";
2
+ import Link from "next/link";
3
+ import { useRouter } from "next/router";
4
+ import { SliceMachineStoreType } from "@src/redux/type";
5
+ import { useSelector } from "react-redux";
6
+
7
+ import { SideNavLink, SideNavListItem } from "@src/components/SideNav";
8
+ import { RadarIcon } from "@src/icons/RadarIcon";
9
+ import { isLoading } from "@src/modules/loading";
10
+ import { LoadingKeysEnum } from "@src/modules/loading/types";
11
+ import {
12
+ HoverCard,
13
+ HoverCardCloseButton,
14
+ HoverCardDescription,
15
+ HoverCardMedia,
16
+ HoverCardTitle,
17
+ } from "@src/components/HoverCard";
18
+ import {
19
+ userHasSeenChangesToolTip,
20
+ userHasSeenSimulatorToolTip,
21
+ } from "@src/modules/userContext";
22
+ import useSliceMachineActions from "@src/modules/useSliceMachineActions";
23
+ import { ChangesRightElement } from "./ChangesRightElement";
24
+
25
+ export const ChangesListItem: FC = () => {
26
+ const { setSeenChangesToolTip } = useSliceMachineActions();
27
+ const open = useOpenChangesHoverCard();
28
+ const router = useRouter();
29
+
30
+ const onClose = () => {
31
+ setSeenChangesToolTip();
32
+ };
33
+
34
+ return (
35
+ <HoverCard
36
+ open={open}
37
+ openDelay={3000}
38
+ onClose={onClose}
39
+ side="right"
40
+ sideOffset={24}
41
+ collisionPadding={280}
42
+ trigger={
43
+ <SideNavListItem>
44
+ <SideNavLink
45
+ title="Changes"
46
+ href="/changes"
47
+ active={router.asPath.startsWith("/changes")}
48
+ component={Link}
49
+ Icon={RadarIcon}
50
+ RightElement={<ChangesRightElement />}
51
+ />
52
+ </SideNavListItem>
53
+ }
54
+ >
55
+ <HoverCardTitle>Push your changes</HoverCardTitle>
56
+ <HoverCardMedia component="image" src="/push.png" />
57
+ <HoverCardDescription>
58
+ When you click Save, your changes are saved locally. Then, you can push
59
+ your models to Prismic from the Changes page.
60
+ </HoverCardDescription>
61
+ <HoverCardCloseButton>Got it</HoverCardCloseButton>
62
+ </HoverCard>
63
+ );
64
+ };
65
+
66
+ const useOpenChangesHoverCard = () => {
67
+ const {
68
+ hasSeenChangesToolTip,
69
+ hasSeenSimulatorToolTip,
70
+ isSavingCustomType,
71
+ isSavingSlice,
72
+ } = useSelector((store: SliceMachineStoreType) => ({
73
+ hasSeenChangesToolTip: userHasSeenChangesToolTip(store),
74
+ hasSeenSimulatorToolTip: userHasSeenSimulatorToolTip(store),
75
+ isSavingCustomType: isLoading(store, LoadingKeysEnum.SAVE_CUSTOM_TYPE),
76
+ isSavingSlice: isLoading(store, LoadingKeysEnum.SAVE_SLICE),
77
+ }));
78
+
79
+ const isSaving = isSavingCustomType || isSavingSlice;
80
+ const [prevIsSaving, setPrevIsSaving] = useState(isSaving);
81
+
82
+ if (!prevIsSaving && isSaving) {
83
+ setPrevIsSaving(isSaving);
84
+ }
85
+
86
+ return (
87
+ !hasSeenChangesToolTip &&
88
+ hasSeenSimulatorToolTip &&
89
+ !isSaving &&
90
+ prevIsSaving
91
+ );
92
+ };