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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type FC } from "react";
|
|
2
|
+
import { useRouter } from "next/router";
|
|
3
|
+
import { Box, Button, Text } from "@prismicio/editor-ui";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
HoverCard,
|
|
7
|
+
HoverCardCloseButton,
|
|
8
|
+
HoverCardDescription,
|
|
9
|
+
HoverCardMedia,
|
|
10
|
+
HoverCardTitle,
|
|
11
|
+
} from "@src/components/HoverCard";
|
|
12
|
+
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
13
|
+
import { useNetwork } from "@src/hooks/useNetwork";
|
|
14
|
+
import { useAuthStatus } from "@src/hooks/useAuthStatus";
|
|
15
|
+
import { useUnSyncChanges } from "@src/features/sync/useUnSyncChanges";
|
|
16
|
+
import { AuthStatus } from "@src/modules/userContext/types";
|
|
17
|
+
import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
|
|
18
|
+
import { AutoSyncStatusIndicator } from "@src/features/sync/components/AutoSyncStatusIndicator";
|
|
19
|
+
|
|
20
|
+
export const ChangesItem: FC = () => {
|
|
21
|
+
const { setSeenChangesToolTip } = useSliceMachineActions();
|
|
22
|
+
const open = useOpenChangesHoverCard();
|
|
23
|
+
const router = useRouter();
|
|
24
|
+
const { autoSyncStatus } = useAutoSync();
|
|
25
|
+
|
|
26
|
+
const onClose = () => {
|
|
27
|
+
setSeenChangesToolTip();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<HoverCard
|
|
32
|
+
open={open}
|
|
33
|
+
openDelay={3000}
|
|
34
|
+
onClose={onClose}
|
|
35
|
+
side="right"
|
|
36
|
+
sideOffset={24}
|
|
37
|
+
collisionPadding={280}
|
|
38
|
+
trigger={
|
|
39
|
+
<Box padding={{ bottom: 24 }}>
|
|
40
|
+
{autoSyncStatus === "failed" ||
|
|
41
|
+
autoSyncStatus === "synced" ||
|
|
42
|
+
autoSyncStatus === "syncing" ? (
|
|
43
|
+
<AutoSyncStatusIndicator autoSyncStatus={autoSyncStatus} />
|
|
44
|
+
) : (
|
|
45
|
+
// TODO(DT-1942): This should be a Button with a link component for
|
|
46
|
+
// accessibility
|
|
47
|
+
<Button
|
|
48
|
+
color="grey"
|
|
49
|
+
onClick={() => {
|
|
50
|
+
void router.push("/changes");
|
|
51
|
+
}}
|
|
52
|
+
sx={{ width: "100%" }}
|
|
53
|
+
>
|
|
54
|
+
<Box alignItems="center" gap={4}>
|
|
55
|
+
<Text variant="bold">Review changes</Text> <ChangesCount />
|
|
56
|
+
</Box>
|
|
57
|
+
</Button>
|
|
58
|
+
)}
|
|
59
|
+
</Box>
|
|
60
|
+
}
|
|
61
|
+
>
|
|
62
|
+
<HoverCardTitle>Push your changes</HoverCardTitle>
|
|
63
|
+
<HoverCardMedia component="image" src="/push.png" />
|
|
64
|
+
<HoverCardDescription>
|
|
65
|
+
When you click Save, your changes are saved locally. Then, you can push
|
|
66
|
+
your models to Prismic from the Changes page.
|
|
67
|
+
</HoverCardDescription>
|
|
68
|
+
<HoverCardCloseButton>Got it</HoverCardCloseButton>
|
|
69
|
+
</HoverCard>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const ChangesCount: FC = () => {
|
|
74
|
+
const isOnline = useNetwork();
|
|
75
|
+
const authStatus = useAuthStatus();
|
|
76
|
+
const { unSyncedSlices, unSyncedCustomTypes } = useUnSyncChanges();
|
|
77
|
+
const numberOfChanges = unSyncedSlices.length + unSyncedCustomTypes.length;
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
!isOnline ||
|
|
81
|
+
authStatus === AuthStatus.UNAUTHORIZED ||
|
|
82
|
+
authStatus === AuthStatus.FORBIDDEN
|
|
83
|
+
) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (numberOfChanges === 0) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const formattedNumberOfChanges = numberOfChanges > 9 ? "+9" : numberOfChanges;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Box padding={{ inline: 6 }} borderRadius={10} backgroundColor="grey5">
|
|
95
|
+
<Text color="grey11" variant="small">
|
|
96
|
+
{formattedNumberOfChanges}
|
|
97
|
+
</Text>
|
|
98
|
+
</Box>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// TODO(DT-1925): Reactivate this feature
|
|
103
|
+
const useOpenChangesHoverCard = () => {
|
|
104
|
+
// const { hasSeenChangesToolTip, hasSeenSimulatorToolTip } = useSelector(
|
|
105
|
+
// (store: SliceMachineStoreType) => ({
|
|
106
|
+
// hasSeenChangesToolTip: userHasSeenChangesToolTip(store),
|
|
107
|
+
// hasSeenSimulatorToolTip: userHasSeenSimulatorToolTip(store),
|
|
108
|
+
// }),
|
|
109
|
+
// );
|
|
110
|
+
|
|
111
|
+
// return (
|
|
112
|
+
// !hasSeenChangesToolTip &&
|
|
113
|
+
// hasSeenSimulatorToolTip
|
|
114
|
+
// );
|
|
115
|
+
|
|
116
|
+
return false;
|
|
117
|
+
};
|
|
@@ -1,25 +1,40 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import {
|
|
2
3
|
Environment as EnvironmentType,
|
|
3
4
|
isUnauthenticatedError,
|
|
4
5
|
isUnauthorizedError,
|
|
5
6
|
} from "@slicemachine/manager/client";
|
|
6
7
|
|
|
7
|
-
import { telemetry } from "@src/apiClient";
|
|
8
|
+
import { getState, telemetry } from "@src/apiClient";
|
|
8
9
|
import { useEnvironments } from "@src/features/environments/useEnvironments";
|
|
9
10
|
import { setEnvironment } from "@src/features/environments/actions/setEnvironment";
|
|
10
11
|
import { useActiveEnvironment } from "@src/features/environments/useActiveEnvironment";
|
|
11
|
-
import { getLegacySliceMachineState } from "@src/features/legacyState/actions/getLegacySliceMachineState";
|
|
12
12
|
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
13
13
|
import { SideNavEnvironmentSelector } from "@src/components/SideNav";
|
|
14
14
|
import { useNetwork } from "@src/hooks/useNetwork";
|
|
15
|
+
import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
|
|
16
|
+
import { normalizeFrontendSlices } from "@lib/models/common/normalizers/slices";
|
|
17
|
+
import { normalizeFrontendCustomTypes } from "@lib/models/common/normalizers/customType";
|
|
18
|
+
import { getUnSyncedChanges } from "@src/features/sync/getUnSyncChanges";
|
|
19
|
+
import { useAuthStatus } from "@src/hooks/useAuthStatus";
|
|
15
20
|
|
|
16
21
|
export function Environment() {
|
|
17
22
|
const { environments, error: useEnvironmentsError } = useEnvironments();
|
|
18
23
|
const { activeEnvironment } = useActiveEnvironment();
|
|
19
24
|
const { refreshState, openLoginModal } = useSliceMachineActions();
|
|
25
|
+
const { syncChanges } = useAutoSync();
|
|
20
26
|
const isOnline = useNetwork();
|
|
27
|
+
const authStatus = useAuthStatus();
|
|
28
|
+
const [isSwitchingEnv, setIsSwitchingEnv] = useState(false);
|
|
29
|
+
const { autoSyncStatus } = useAutoSync();
|
|
21
30
|
|
|
22
31
|
async function onSelect(environment: EnvironmentType) {
|
|
32
|
+
if (activeEnvironment?.name === environment.name) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setIsSwitchingEnv(true);
|
|
37
|
+
|
|
23
38
|
void telemetry.track({
|
|
24
39
|
event: "environment:switch",
|
|
25
40
|
domain: environment.domain,
|
|
@@ -27,9 +42,39 @@ export function Environment() {
|
|
|
27
42
|
|
|
28
43
|
await setEnvironment(environment);
|
|
29
44
|
|
|
30
|
-
const
|
|
45
|
+
const serverState = await getState();
|
|
46
|
+
refreshState(serverState);
|
|
47
|
+
|
|
48
|
+
const slices = normalizeFrontendSlices(
|
|
49
|
+
serverState.libraries,
|
|
50
|
+
serverState.remoteSlices,
|
|
51
|
+
);
|
|
52
|
+
const customTypes = Object.values(
|
|
53
|
+
normalizeFrontendCustomTypes(
|
|
54
|
+
serverState.customTypes,
|
|
55
|
+
serverState.remoteCustomTypes,
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
const { changedCustomTypes, changedSlices } = getUnSyncedChanges({
|
|
59
|
+
authStatus,
|
|
60
|
+
customTypes,
|
|
61
|
+
isOnline,
|
|
62
|
+
libraries: serverState.libraries,
|
|
63
|
+
slices,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (
|
|
67
|
+
environment.kind === "dev" &&
|
|
68
|
+
(changedCustomTypes.length > 0 || changedSlices.length > 0)
|
|
69
|
+
) {
|
|
70
|
+
syncChanges({
|
|
71
|
+
environment,
|
|
72
|
+
changedCustomTypes,
|
|
73
|
+
changedSlices,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
31
76
|
|
|
32
|
-
|
|
77
|
+
setIsSwitchingEnv(false);
|
|
33
78
|
}
|
|
34
79
|
|
|
35
80
|
if (!isOnline) {
|
|
@@ -42,6 +87,8 @@ export function Environment() {
|
|
|
42
87
|
environments={environments}
|
|
43
88
|
activeEnvironment={activeEnvironment}
|
|
44
89
|
onSelect={onSelect}
|
|
90
|
+
disabled={isSwitchingEnv || autoSyncStatus === "syncing"}
|
|
91
|
+
loading={isSwitchingEnv}
|
|
45
92
|
/>
|
|
46
93
|
);
|
|
47
94
|
}
|
|
@@ -131,10 +131,8 @@ describe("Side Navigation", () => {
|
|
|
131
131
|
test.skip.each([
|
|
132
132
|
["Page types", "/"],
|
|
133
133
|
["Custom types", "/custom-types"],
|
|
134
|
-
["Changes", "/changes"],
|
|
135
|
-
|
|
136
|
-
["Changelog", "/changelog"],
|
|
137
134
|
["Slices", "/slices"],
|
|
135
|
+
["Changelog", "/changelog"],
|
|
138
136
|
// TODO: once we have a plan fo how to display individual libraries change this
|
|
139
137
|
// ["Slices/a", "/slices#slices/a"],
|
|
140
138
|
// ["Slices/b", "/slices#slices/b"]
|
|
@@ -156,95 +154,17 @@ describe("Side Navigation", () => {
|
|
|
156
154
|
},
|
|
157
155
|
);
|
|
158
156
|
|
|
159
|
-
test("should display the number of changes on the '
|
|
157
|
+
test("should display the number of changes on the 'Review changes' item", async () => {
|
|
160
158
|
renderSideNavigation({ canUpdate: true, hasChanges: true });
|
|
161
159
|
|
|
162
|
-
expect(await screen.findByText("
|
|
160
|
+
expect(await screen.findByText("Review changes")).toBeVisible();
|
|
163
161
|
const changesItem = screen
|
|
164
|
-
.getByText("
|
|
165
|
-
.closest("
|
|
162
|
+
.getByText("Review changes")
|
|
163
|
+
.closest("button") as HTMLButtonElement;
|
|
166
164
|
|
|
167
165
|
expect(within(changesItem).getByText("1")).toBeVisible();
|
|
168
166
|
});
|
|
169
167
|
|
|
170
|
-
test("should not display the number of changes or 'Disconnect' on the 'Changes' item", async () => {
|
|
171
|
-
renderSideNavigation({ canUpdate: true, hasChanges: false });
|
|
172
|
-
|
|
173
|
-
expect(await screen.findByText("Changes")).toBeVisible();
|
|
174
|
-
const changesItem = screen
|
|
175
|
-
.getByText("Changes")
|
|
176
|
-
.closest("a") as HTMLAnchorElement;
|
|
177
|
-
|
|
178
|
-
expect(within(changesItem).queryByText("1")).not.toBeInTheDocument();
|
|
179
|
-
expect(
|
|
180
|
-
within(changesItem).queryByText("Logged out"),
|
|
181
|
-
).not.toBeInTheDocument();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test("should display the information that user is disconnected on the 'Changes' item when unauthorized", async () => {
|
|
185
|
-
renderSideNavigation({
|
|
186
|
-
canUpdate: true,
|
|
187
|
-
hasChanges: true,
|
|
188
|
-
authStatus: AuthStatus.UNAUTHORIZED,
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
expect(await screen.findByText("Changes")).toBeVisible();
|
|
192
|
-
const changesItem = screen
|
|
193
|
-
.getByText("Changes")
|
|
194
|
-
.closest("a") as HTMLAnchorElement;
|
|
195
|
-
|
|
196
|
-
expect(within(changesItem).getByText("Logged out")).toBeVisible();
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("should display the information that user is disconnected on the 'Changes' item when forbidden", async () => {
|
|
200
|
-
renderSideNavigation({
|
|
201
|
-
canUpdate: true,
|
|
202
|
-
hasChanges: true,
|
|
203
|
-
authStatus: AuthStatus.FORBIDDEN,
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
expect(await screen.findByText("Changes")).toBeVisible();
|
|
207
|
-
const changesItem = screen
|
|
208
|
-
.getByText("Changes")
|
|
209
|
-
.closest("a") as HTMLAnchorElement;
|
|
210
|
-
|
|
211
|
-
expect(within(changesItem).getByText("Logged out")).toBeVisible();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
test("should display the information that user is disconnected on the 'Changes' item when offline", async () => {
|
|
215
|
-
vi.spyOn(navigator, "onLine", "get").mockReturnValueOnce(false);
|
|
216
|
-
|
|
217
|
-
renderSideNavigation({
|
|
218
|
-
canUpdate: true,
|
|
219
|
-
hasChanges: true,
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
expect(await screen.findByText("Changes")).toBeVisible();
|
|
223
|
-
const changesItem = screen
|
|
224
|
-
.getByText("Changes")
|
|
225
|
-
.closest("a") as HTMLAnchorElement;
|
|
226
|
-
|
|
227
|
-
expect(within(changesItem).getByText("Logged out")).toBeVisible();
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
test("should not display the information that user is disconnected when user is online", async () => {
|
|
231
|
-
vi.spyOn(navigator, "onLine", "get").mockReturnValueOnce(true);
|
|
232
|
-
|
|
233
|
-
renderSideNavigation({
|
|
234
|
-
canUpdate: true,
|
|
235
|
-
hasChanges: true,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
expect(await screen.findByText("Changes")).toBeVisible();
|
|
239
|
-
const changesItem = screen
|
|
240
|
-
.getByText("Changes")
|
|
241
|
-
.closest("a") as HTMLAnchorElement;
|
|
242
|
-
|
|
243
|
-
expect(
|
|
244
|
-
within(changesItem).queryByText("Logged out"),
|
|
245
|
-
).not.toBeInTheDocument();
|
|
246
|
-
});
|
|
247
|
-
|
|
248
168
|
test("Video Item with next", async (ctx) => {
|
|
249
169
|
const adapter = createTestPlugin({
|
|
250
170
|
meta: {
|
|
@@ -8,9 +8,9 @@ import { telemetry } from "@src/apiClient";
|
|
|
8
8
|
import VideoItem from "@components/Navigation/VideoItem";
|
|
9
9
|
import { LightningIcon } from "@src/icons/Lightning";
|
|
10
10
|
import { MathPlusIcon } from "@src/icons/MathPlusIcon";
|
|
11
|
+
import { SettingsIcon } from "@src/icons/SettingsIcon";
|
|
11
12
|
import { CUSTOM_TYPES_CONFIG } from "@src/features/customTypes/customTypesConfig";
|
|
12
13
|
import {
|
|
13
|
-
SideNavSeparator,
|
|
14
14
|
SideNavLink,
|
|
15
15
|
SideNavListItem,
|
|
16
16
|
SideNavList,
|
|
@@ -26,9 +26,10 @@ import { SliceMachineStoreType } from "@src/redux/type";
|
|
|
26
26
|
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
|
|
27
27
|
import { getChangelog } from "@src/modules/environment";
|
|
28
28
|
import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
|
|
29
|
+
import { useGitIntegrationExperiment } from "@src/features/settings/git/useGitIntegrationExperiment";
|
|
29
30
|
import { useRepositoryInformation } from "@src/hooks/useRepositoryInformation";
|
|
30
31
|
|
|
31
|
-
import {
|
|
32
|
+
import { ChangesItem } from "./ChangesItem";
|
|
32
33
|
import { Environment } from "./Environment";
|
|
33
34
|
|
|
34
35
|
import * as styles from "./index.css";
|
|
@@ -45,6 +46,7 @@ const Navigation: FC = () => {
|
|
|
45
46
|
useSliceMachineActions();
|
|
46
47
|
const { repositoryName, repositoryDomain, repositoryUrl } =
|
|
47
48
|
useRepositoryInformation();
|
|
49
|
+
const gitIntegrationExperiment = useGitIntegrationExperiment();
|
|
48
50
|
|
|
49
51
|
return (
|
|
50
52
|
<SideNav>
|
|
@@ -73,6 +75,8 @@ const Navigation: FC = () => {
|
|
|
73
75
|
href={repositoryUrl}
|
|
74
76
|
/>
|
|
75
77
|
|
|
78
|
+
<ChangesItem />
|
|
79
|
+
|
|
76
80
|
<SideNavList>
|
|
77
81
|
<SideNavListItem>
|
|
78
82
|
<SideNavLink
|
|
@@ -104,12 +108,6 @@ const Navigation: FC = () => {
|
|
|
104
108
|
/>
|
|
105
109
|
</SideNavListItem>
|
|
106
110
|
|
|
107
|
-
<SideNavSeparator />
|
|
108
|
-
|
|
109
|
-
<ChangesListItem />
|
|
110
|
-
|
|
111
|
-
<SideNavSeparator />
|
|
112
|
-
|
|
113
111
|
<SideNavListItem>
|
|
114
112
|
<SideNavLink
|
|
115
113
|
title="Slices"
|
|
@@ -141,17 +139,19 @@ const Navigation: FC = () => {
|
|
|
141
139
|
)}
|
|
142
140
|
|
|
143
141
|
<SideNavList position="bottom">
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
142
|
+
<SideNavListItem>
|
|
143
|
+
<SideNavLink
|
|
144
|
+
title="Invite team"
|
|
145
|
+
href={`${repositoryUrl}/settings/users`}
|
|
146
|
+
Icon={MathPlusIcon}
|
|
147
|
+
onClick={() => {
|
|
148
|
+
void telemetry.track({
|
|
149
|
+
event: "users-invite-button-clicked",
|
|
150
|
+
});
|
|
151
|
+
}}
|
|
152
|
+
target="_blank"
|
|
153
|
+
/>
|
|
154
|
+
</SideNavListItem>
|
|
155
155
|
|
|
156
156
|
<ErrorBoundary>
|
|
157
157
|
<Suspense>
|
|
@@ -162,11 +162,23 @@ const Navigation: FC = () => {
|
|
|
162
162
|
</Suspense>
|
|
163
163
|
</ErrorBoundary>
|
|
164
164
|
|
|
165
|
+
{gitIntegrationExperiment.eligible ? (
|
|
166
|
+
<SideNavListItem>
|
|
167
|
+
<SideNavLink
|
|
168
|
+
title="Settings"
|
|
169
|
+
href="/settings"
|
|
170
|
+
Icon={SettingsIcon}
|
|
171
|
+
active={router.asPath.startsWith("/settings")}
|
|
172
|
+
component={Link}
|
|
173
|
+
/>
|
|
174
|
+
</SideNavListItem>
|
|
175
|
+
) : undefined}
|
|
176
|
+
|
|
165
177
|
<SideNavListItem>
|
|
166
178
|
<SideNavLink
|
|
167
179
|
title="Changelog"
|
|
168
180
|
href="/changelog"
|
|
169
|
-
Icon={
|
|
181
|
+
Icon={LightningIcon}
|
|
170
182
|
active={router.asPath.startsWith("/changelog")}
|
|
171
183
|
component={Link}
|
|
172
184
|
RightElement={
|
|
@@ -21,7 +21,7 @@ import { useSliceState } from "@src/features/slices/sliceBuilder/SliceBuilderPro
|
|
|
21
21
|
import { AutoSaveStatusIndicator } from "@src/features/autoSave/AutoSaveStatusIndicator";
|
|
22
22
|
|
|
23
23
|
export const SliceBuilder: FC = () => {
|
|
24
|
-
const { slice,
|
|
24
|
+
const { slice, actionQueueStatus } = useSliceState();
|
|
25
25
|
|
|
26
26
|
const isSimulatorAvailableForFramework = useSelector(
|
|
27
27
|
selectIsSimulatorAvailableForFramework,
|
|
@@ -33,10 +33,10 @@ export const SliceBuilder: FC = () => {
|
|
|
33
33
|
<AppLayoutBackButton url="/slices" />
|
|
34
34
|
<AppLayoutBreadcrumb folder="Slices" page={slice.model.name} />
|
|
35
35
|
<AppLayoutActions>
|
|
36
|
-
<AutoSaveStatusIndicator status={
|
|
36
|
+
<AutoSaveStatusIndicator status={actionQueueStatus} />
|
|
37
37
|
<SimulatorButton
|
|
38
38
|
isSimulatorAvailableForFramework={isSimulatorAvailableForFramework}
|
|
39
|
-
disabled={
|
|
39
|
+
disabled={actionQueueStatus !== "done"}
|
|
40
40
|
/>
|
|
41
41
|
</AppLayoutActions>
|
|
42
42
|
</AppLayoutHeader>
|
|
@@ -13,7 +13,6 @@ const WidgetForm = ({
|
|
|
13
13
|
return (
|
|
14
14
|
<Box>
|
|
15
15
|
<Formik
|
|
16
|
-
validateOnChange
|
|
17
16
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
18
17
|
initialValues={initialValues}
|
|
19
18
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-assignment
|
|
@@ -117,3 +117,28 @@ export function computeModelStatus(
|
|
|
117
117
|
: compareCustomTypeLocalToRemote(model);
|
|
118
118
|
return { status, model };
|
|
119
119
|
}
|
|
120
|
+
|
|
121
|
+
export function computeStatuses(
|
|
122
|
+
models: LocalOrRemoteCustomType[],
|
|
123
|
+
userHasAccessToModels: boolean,
|
|
124
|
+
): { [sliceId: string]: ModelStatus };
|
|
125
|
+
export function computeStatuses(
|
|
126
|
+
models: LocalOrRemoteSlice[],
|
|
127
|
+
userHasAccessToModels: boolean,
|
|
128
|
+
): { [sliceId: string]: ModelStatus };
|
|
129
|
+
export function computeStatuses(
|
|
130
|
+
models: LocalOrRemoteModel[],
|
|
131
|
+
userHasAccessToModels: boolean,
|
|
132
|
+
) {
|
|
133
|
+
return models.reduce<{ [id: string]: ModelStatus }>(
|
|
134
|
+
(acc, model) => {
|
|
135
|
+
const { status } = computeModelStatus(model, userHasAccessToModels);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
...acc,
|
|
139
|
+
[hasLocal(model) ? model.local.id : model.remote.id]: status,
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
{} as { [sliceId: string]: ModelStatus },
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -51,7 +51,7 @@ export const StructuredTextWidget: Widget<RichText, typeof schema> = {
|
|
|
51
51
|
label,
|
|
52
52
|
placeholder: "",
|
|
53
53
|
allowTargetBlank: true,
|
|
54
|
-
|
|
54
|
+
multi: optionValues.join(","),
|
|
55
55
|
},
|
|
56
56
|
}),
|
|
57
57
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
package/out/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/css/
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/css/39e089aad1742a3a.css" as="style"/><link rel="stylesheet" href="/_next/static/css/39e089aad1742a3a.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-2f903acb0cccbf9e.js" defer=""></script><script src="/_next/static/chunks/framework-cdccea7a52cc6e81.js" defer=""></script><script src="/_next/static/chunks/main-5e6780279ca21cb9.js" defer=""></script><script src="/_next/static/chunks/pages/_app-bca191df4ac7078e.js" defer=""></script><script src="/_next/static/chunks/pages/_error-69b4f498bafdd188.js" defer=""></script><script src="/_next/static/dS_xZnzzna6Y6uwcTgf90/_buildManifest.js" defer=""></script><script src="/_next/static/dS_xZnzzna6Y6uwcTgf90/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"dS_xZnzzna6Y6uwcTgf90","runtimeConfig":{"sentryEnvironment":"beta"},"nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|