slice-machine-ui 1.15.1-dev-next-release.2 → 1.15.1-dev-next-release.3

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 (65) hide show
  1. package/components/ChangesItems/ChangesItems.tsx +16 -25
  2. package/components/CustomTypeTable/changesPage.tsx +4 -6
  3. package/lib/builders/CustomTypeBuilder/SliceZone/List.tsx +26 -32
  4. package/lib/builders/CustomTypeBuilder/SliceZone/SlicesTemplatesModal.tsx +1 -0
  5. package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModal.tsx +1 -0
  6. package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModalList.tsx +23 -76
  7. package/next.config.mjs +1 -0
  8. package/out/404.html +1 -1
  9. package/out/[lib]/[sliceName]/[variation]/screenshot.html +1 -1
  10. package/out/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  11. package/out/[lib]/[sliceName]/[variation].html +1 -1
  12. package/out/_next/static/chunks/14-90eaa126dcf1b635.js +1 -0
  13. package/out/_next/static/chunks/{377-3caacee3c3ffdc25.js → 377-467ca51a57342a23.js} +1 -1
  14. package/out/_next/static/chunks/{573-e92018662d1f6c26.js → 573-8678a91b09707f5d.js} +1 -1
  15. package/out/_next/static/chunks/590-d9046f10fcc34a4d.js +1 -0
  16. package/out/_next/static/chunks/{97-f6188ebe22eb21da.js → 97-ee2fa6c3e6bf7b71.js} +1 -1
  17. package/out/_next/static/chunks/pages/[lib]/[sliceName]/[variation]/{simulator-c608e0470a8f6099.js → simulator-47ba090193469e3f.js} +1 -1
  18. package/out/_next/static/chunks/pages/[lib]/[sliceName]/[variation]-89838e684fcaaf5d.js +1 -0
  19. package/out/_next/static/chunks/pages/{_app-0e270aca89a6033d.js → _app-f7e14ddd3e363991.js} +9 -9
  20. package/out/_next/static/chunks/pages/changes-c62c4ac5de9a1a09.js +1 -0
  21. package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-868f09f50fd3039a.js → [customTypeId]-1baa6af0ddf0ab6b.js} +1 -1
  22. package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-b6552cab363f7fbf.js → [pageTypeId]-708b782db680b804.js} +1 -1
  23. package/out/_next/static/chunks/pages/slices-15b69ac3611efbfe.js +1 -0
  24. package/out/_next/static/css/22d69420bda374a7.css +1 -0
  25. package/out/_next/static/css/{b6bfe1e0ef76c2b1.css → 9ddd0cb7fff63603.css} +1 -1
  26. package/out/_next/static/css/f585032018f6024b.css +1 -0
  27. package/out/_next/static/pA_sw-x2_QsAanOp1Lx0c/_buildManifest.js +1 -0
  28. package/out/changelog.html +1 -1
  29. package/out/changes.html +1 -1
  30. package/out/custom-types/[customTypeId].html +1 -1
  31. package/out/custom-types.html +1 -1
  32. package/out/index.html +1 -1
  33. package/out/page-types/[pageTypeId].html +1 -1
  34. package/out/slices.html +1 -1
  35. package/package.json +4 -4
  36. package/pages/slices.tsx +25 -42
  37. package/src/domain/slice.ts +38 -0
  38. package/src/features/changes/StatusBadge.tsx +107 -0
  39. package/src/features/slices/sliceCards/NonSharedSliceViewCard.tsx +39 -0
  40. package/src/features/slices/sliceCards/SharedSliceSelectionCard.tsx +80 -0
  41. package/src/features/slices/sliceCards/SharedSliceViewCard.tsx +147 -0
  42. package/src/modules/pushChangesSaga/trackPushChangesSuccess.ts +1 -1
  43. package/test/pages/custom-types.test.tsx +1 -1
  44. package/test/pages/slices.test.tsx +2 -2
  45. package/components/KebabMenuDropdown/KebabMenuList.tsx +0 -71
  46. package/components/KebabMenuDropdown/index.tsx +0 -64
  47. package/components/StatusBadge/index.tsx +0 -139
  48. package/lib/models/ui/Link.ts +0 -23
  49. package/lib/models/ui/Slice/LegacySliceTooltip.module.css +0 -10
  50. package/lib/models/ui/Slice/index.tsx +0 -424
  51. package/lib/models/ui/Slice/wrappers.tsx +0 -49
  52. package/lib/models/ui/Store.ts +0 -10
  53. package/out/_next/static/chunks/809-d1f83d7413864f03.js +0 -1
  54. package/out/_next/static/chunks/906-9224feb63b5e36f3.js +0 -1
  55. package/out/_next/static/chunks/pages/[lib]/[sliceName]/[variation]-36ba0bde8415ad8b.js +0 -1
  56. package/out/_next/static/chunks/pages/changes-8338c9d0723a7033.js +0 -1
  57. package/out/_next/static/chunks/pages/slices-afa4b34df8f8e1c3.js +0 -1
  58. package/out/_next/static/css/6b6c11ed1fffd3e0.css +0 -1
  59. package/out/_next/static/css/e855bef88bb5345b.css +0 -1
  60. package/out/_next/static/z-OmqvYWKjvP9W4MN_LBy/_buildManifest.js +0 -1
  61. package/src/models/ApiError.ts +0 -6
  62. package/src/models/SyncError.ts +0 -3
  63. package/src/utils/screenshots/missing.ts +0 -4
  64. package/test/src/utils/screenshots/missing.test.ts +0 -51
  65. /package/out/_next/static/{z-OmqvYWKjvP9W4MN_LBy → pA_sw-x2_QsAanOp1Lx0c}/_ssgManifest.js +0 -0
package/pages/slices.tsx CHANGED
@@ -9,7 +9,6 @@ import { SharedSlice as SharedSliceType } from "@prismicio/types-internal/lib/cu
9
9
 
10
10
  import { ComponentUI } from "@lib/models/common/ComponentUI";
11
11
  import { LibraryUI } from "@lib/models/common/LibraryUI";
12
- import { SharedSlice } from "@lib/models/ui/Slice";
13
12
  import { VIDEO_WHAT_ARE_SLICES } from "@lib/consts";
14
13
  import {
15
14
  AppLayout,
@@ -26,13 +25,9 @@ import { RenameSliceModal } from "@components/Forms/RenameSliceModal";
26
25
  import { DeleteSliceModal } from "@components/DeleteSliceModal";
27
26
  import { SliceMachineStoreType } from "@src/redux/type";
28
27
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
29
- import {
30
- getFrontendSlices,
31
- getLibraries,
32
- getRemoteSlices,
33
- } from "@src/modules/slices";
34
- import { useModelStatus } from "@src/hooks/useModelStatus";
28
+ import { getLibraries, getRemoteSlices } from "@src/modules/slices";
35
29
  import { useScreenshotChangesModal } from "@src/hooks/useScreenshotChangesModal";
30
+ import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSliceViewCard";
36
31
  import { SLICES_CONFIG } from "@src/features/slices/slicesConfig";
37
32
  import { SliceToastMessage } from "@components/ToasterContainer";
38
33
 
@@ -45,11 +40,10 @@ const SlicesIndex: React.FunctionComponent = () => {
45
40
 
46
41
  const { sliceFilterFn, defaultVariationSelector } = modalPayload;
47
42
 
48
- const { remoteSlices, libraries, frontendSlices } = useSelector(
43
+ const { remoteSlices, libraries } = useSelector(
49
44
  (store: SliceMachineStoreType) => ({
50
45
  remoteSlices: getRemoteSlices(store),
51
46
  libraries: getLibraries(store),
52
- frontendSlices: getFrontendSlices(store),
53
47
  })
54
48
  );
55
49
  const [isCreateSliceModalOpen, setIsCreateSliceModalOpen] = useState(false);
@@ -65,10 +59,6 @@ const SlicesIndex: React.FunctionComponent = () => {
65
59
  return library;
66
60
  });
67
61
 
68
- const { modelsStatuses, authStatus, isOnline } = useModelStatus({
69
- slices: frontendSlices,
70
- });
71
-
72
62
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
73
63
  const slices = (libraries || []).map((l) => l.components).flat();
74
64
  const sliceCount = slices.length;
@@ -179,39 +169,32 @@ const SlicesIndex: React.FunctionComponent = () => {
179
169
  </Flex>
180
170
  <Grid
181
171
  elems={components}
182
- defineElementKey={(slice: ComponentUI) =>
183
- slice.model.name
184
- }
185
- renderElem={(slice: ComponentUI) => {
186
- return SharedSlice.render({
187
- slice,
188
- StatusOrCustom: {
189
- status: modelsStatuses.slices[slice.model.id],
190
- authStatus,
191
- isOnline,
192
- },
193
- actions: {
194
- onUpdateScreenshot: (e: React.MouseEvent) => {
195
- e.preventDefault();
196
- onOpenModal({
197
- sliceFilterFn: (s: ComponentUI[]) =>
198
- s.filter(
199
- (e) => e.model.id === slice.model.id
200
- ),
201
- });
202
- },
203
- openRenameModal: (slice: ComponentUI) => {
172
+ defineElementKey={(slice) => slice.model.name}
173
+ renderElem={(slice) => (
174
+ <SharedSliceViewCard
175
+ action={{
176
+ type: "menu",
177
+ onRemove: () => {
204
178
  setSliceForEdit(slice);
205
- openRenameSliceModal();
179
+ openDeleteSliceModal();
206
180
  },
207
- openDeleteModal: (slice: ComponentUI) => {
181
+ onRename: () => {
208
182
  setSliceForEdit(slice);
209
- openDeleteSliceModal();
183
+ openRenameSliceModal();
210
184
  },
211
- },
212
- showActions: true,
213
- });
214
- }}
185
+ }}
186
+ isDeletedSlice={false}
187
+ onUpdateScreenshot={() => {
188
+ onOpenModal({
189
+ sliceFilterFn: (s) =>
190
+ s.filter(
191
+ (e) => e.model.id === slice.model.id
192
+ ),
193
+ });
194
+ }}
195
+ slice={slice}
196
+ />
197
+ )}
215
198
  gridGap="32px 16px"
216
199
  />
217
200
  </Flex>
@@ -0,0 +1,38 @@
1
+ import type {
2
+ CompositeSlice,
3
+ LegacySlice,
4
+ } from "@prismicio/types-internal/lib/customtypes/widgets/slices";
5
+
6
+ import type { ComponentUI } from "@lib/models/common/ComponentUI";
7
+ import type { VariationSM } from "@lib/models/common/Slice";
8
+
9
+ export type NonSharedSlice = CompositeSlice | LegacySlice;
10
+
11
+ export const NON_SHARED_SLICE_LIBRARY_NAME = "Default";
12
+
13
+ export function countMissingScreenshots(slice: ComponentUI): number {
14
+ return slice.model.variations.length - Object.keys(slice.screenshots).length;
15
+ }
16
+
17
+ export function getNonSharedSliceLabel(slice: NonSharedSlice): string {
18
+ return (
19
+ slice.config?.label ??
20
+ (slice.type === "Group" ||
21
+ slice.type === "Slice" ||
22
+ (slice.type !== "Boolean" && slice.type !== "Separator")
23
+ ? slice.fieldset
24
+ : undefined) ??
25
+ slice.type
26
+ );
27
+ }
28
+
29
+ export function getScreenshotUrl(
30
+ slice: ComponentUI,
31
+ variation: VariationSM
32
+ ): string | undefined {
33
+ return slice.screenshots[variation.id]?.url;
34
+ }
35
+
36
+ export function getSharedSliceLibraryName(slice: ComponentUI): string {
37
+ return slice.from.length > 0 ? slice.from : "Default";
38
+ }
@@ -0,0 +1,107 @@
1
+ import { Badge, Tooltip } from "@prismicio/editor-ui";
2
+ import type { ComponentProps, FC } from "react";
3
+
4
+ import { ModelStatus } from "@lib/models/common/ModelStatus";
5
+ import { AuthStatus } from "@src/modules/userContext/types";
6
+
7
+ export type StatusBadgeProps = GetStatusBadgeContentArgs;
8
+
9
+ export const StatusBadge: FC<StatusBadgeProps> = (props) => {
10
+ const { badgeColor, badgeTitle, tooltipContent } =
11
+ getStatusBadgeContent(props);
12
+ return (
13
+ <Tooltip content={tooltipContent} side="bottom">
14
+ <Badge color={badgeColor} title={badgeTitle} />
15
+ </Tooltip>
16
+ );
17
+ };
18
+
19
+ type GetStatusBadgeContentArgs = {
20
+ authStatus: AuthStatus;
21
+ isOnline: boolean;
22
+ modelStatus: ModelStatus;
23
+ modelType: ModelType;
24
+ };
25
+
26
+ type ModelType = "CustomType" | "Slice";
27
+
28
+ type StatusBadgeContent = {
29
+ badgeColor: ComponentProps<typeof Badge>["color"];
30
+ badgeTitle: string;
31
+ tooltipContent: string;
32
+ };
33
+
34
+ function getStatusBadgeContent(
35
+ args: GetStatusBadgeContentArgs
36
+ ): StatusBadgeContent {
37
+ const modelTypeLabel = modelTypeLabels[args.modelType];
38
+ switch (args.modelStatus) {
39
+ case ModelStatus.New: {
40
+ return {
41
+ badgeColor: "green",
42
+ badgeTitle: "New",
43
+ tooltipContent: `This ${modelTypeLabel} exists only locally. Upon sync, it will be pushed to your remote repository.`,
44
+ };
45
+ }
46
+ case ModelStatus.Modified: {
47
+ return {
48
+ badgeColor: "amber",
49
+ badgeTitle: "Modified",
50
+ tooltipContent: `This ${modelTypeLabel} has been modified locally. Upon sync, changes will be pushed to your remote repository.`,
51
+ };
52
+ }
53
+ case ModelStatus.Synced: {
54
+ return {
55
+ badgeColor: "purple",
56
+ badgeTitle: "Synced",
57
+ tooltipContent: `This ${modelTypeLabel} is in sync with the remote repository.`,
58
+ };
59
+ }
60
+ case ModelStatus.Deleted: {
61
+ return {
62
+ badgeColor: "tomato",
63
+ badgeTitle: "Deleted",
64
+ tooltipContent: `This ${modelTypeLabel} has been deleted locally.`,
65
+ };
66
+ }
67
+ case ModelStatus.Unknown: {
68
+ if (!args.isOnline) {
69
+ return {
70
+ badgeColor: "grey",
71
+ badgeTitle: "Unknown",
72
+ tooltipContent:
73
+ "Data from the remote repository could not be fetched (no internet connection).",
74
+ };
75
+ }
76
+ if (args.authStatus === AuthStatus.UNAUTHORIZED) {
77
+ return {
78
+ badgeColor: "grey",
79
+ badgeTitle: "Unknown",
80
+ tooltipContent:
81
+ "Data from the remote repository could not be fetched (not connected to Prismic).",
82
+ };
83
+ }
84
+ if (args.authStatus === AuthStatus.FORBIDDEN) {
85
+ return {
86
+ badgeColor: "grey",
87
+ badgeTitle: "Unknown",
88
+ tooltipContent:
89
+ "Data from the remote repository could not be fetched (you don't have access to the repository).",
90
+ };
91
+ }
92
+ }
93
+ default: {
94
+ return {
95
+ badgeColor: "grey",
96
+ badgeTitle: "Unknown",
97
+ tooltipContent:
98
+ "Data from the remote repository could not be fetched (unknown error).",
99
+ };
100
+ }
101
+ }
102
+ }
103
+
104
+ const modelTypeLabels: Record<ModelType, string> = {
105
+ CustomType: "type",
106
+ Slice: "slice",
107
+ };
@@ -0,0 +1,39 @@
1
+ import { Badge, Box, Text, Tooltip } from "@prismicio/editor-ui";
2
+ import type { FC } from "react";
3
+
4
+ import { Card, CardActions, CardFooter, CardMedia } from "@src/components/Card";
5
+ import {
6
+ getNonSharedSliceLabel,
7
+ NON_SHARED_SLICE_LIBRARY_NAME,
8
+ type NonSharedSlice,
9
+ } from "@src/domain/slice";
10
+
11
+ type NonSharedSliceViewCardProps = {
12
+ slice: NonSharedSlice;
13
+ };
14
+
15
+ export const NonSharedSliceViewCard: FC<NonSharedSliceViewCardProps> = ({
16
+ slice,
17
+ }) => (
18
+ <Card>
19
+ <CardMedia component="div">
20
+ <Box alignItems="center" justifyContent="center">
21
+ <Text color="grey11" component="span">
22
+ No screenshot available
23
+ </Text>
24
+ </Box>
25
+ </CardMedia>
26
+ <CardActions>
27
+ <Tooltip
28
+ content="This Slice was created with the Legacy Builder, and is incompatible with Slice Machine. You cannot edit, push, or delete it in Slice Machine. In order to proceed, manually remove the Slice from your type model. Then create a new Slice with the same fields using Slice Machine."
29
+ side="bottom"
30
+ >
31
+ <Badge color="purple" title="Legacy Slice" />
32
+ </Tooltip>
33
+ </CardActions>
34
+ <CardFooter
35
+ subtitle={NON_SHARED_SLICE_LIBRARY_NAME}
36
+ title={getNonSharedSliceLabel(slice)}
37
+ />
38
+ </Card>
39
+ );
@@ -0,0 +1,80 @@
1
+ import { Box, Checkbox, Text } from "@prismicio/editor-ui";
2
+ import type { FC } from "react";
3
+
4
+ import { ComponentUI } from "@lib/models/common/ComponentUI";
5
+ import { Card, CardFooter, CardMedia } from "@src/components/Card";
6
+ import { getScreenshotUrl, getSharedSliceLibraryName } from "@src/domain/slice";
7
+
8
+ type SharedSliceSelectionCardProps = {
9
+ isComingSoon: boolean;
10
+ isSliceTemplate: boolean;
11
+ onSelectedChange: (selected: boolean) => void;
12
+ selected: boolean;
13
+ slice: ComponentUI;
14
+ };
15
+
16
+ export const SharedSliceSelectionCard: FC<SharedSliceSelectionCardProps> = ({
17
+ isComingSoon,
18
+ isSliceTemplate,
19
+ onSelectedChange,
20
+ selected,
21
+ slice,
22
+ }) => {
23
+ const defaultVariation = ComponentUI.variation(slice);
24
+ if (!defaultVariation) return null;
25
+ const src = getScreenshotUrl(slice, defaultVariation);
26
+ return (
27
+ <Card
28
+ checked={selected}
29
+ data-cy={`shared-slice-selection-card-${slice.model.id}`}
30
+ data-testid="shared-slice-selection-card"
31
+ disabled={isComingSoon}
32
+ interactive
33
+ onClick={() => {
34
+ onSelectedChange(!selected);
35
+ }}
36
+ size="small"
37
+ variant="outlined"
38
+ >
39
+ {src !== undefined ? (
40
+ <CardMedia src={src} />
41
+ ) : (
42
+ <CardMedia component="div">
43
+ <Box alignItems="center" justifyContent="center">
44
+ <Text color="grey11" component="span">
45
+ No screenshot available
46
+ </Text>
47
+ </Box>
48
+ </CardMedia>
49
+ )}
50
+ <CardFooter
51
+ action={
52
+ // TODO(DT-1661): `findFocusableAncestor` should find Radix UI's `Checkbox`.
53
+ <div onClick={(event) => event.stopPropagation()}>
54
+ <Checkbox
55
+ checked={selected}
56
+ disabled={isComingSoon}
57
+ onCheckedChange={onSelectedChange}
58
+ />
59
+ </div>
60
+ }
61
+ subtitle={
62
+ <>
63
+ {isSliceTemplate
64
+ ? `${slice.model.variations.length} variation${
65
+ slice.model.variations.length > 1 ? "s" : ""
66
+ }`
67
+ : getSharedSliceLibraryName(slice)}
68
+ {isComingSoon ? (
69
+ <Text color="purple11" component="span" variant="small">
70
+ {" "}
71
+ • (coming soon)
72
+ </Text>
73
+ ) : undefined}
74
+ </>
75
+ }
76
+ title={slice.model.name}
77
+ />
78
+ </Card>
79
+ );
80
+ };
@@ -0,0 +1,147 @@
1
+ import {
2
+ Box,
3
+ Button,
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuItem,
7
+ DropdownMenuTrigger,
8
+ Icon,
9
+ IconButton,
10
+ Text,
11
+ tokens,
12
+ } from "@prismicio/editor-ui";
13
+ import Link from "next/link";
14
+ import type { FC } from "react";
15
+
16
+ import { ComponentUI } from "@lib/models/common/ComponentUI";
17
+ import { Card, CardFooter, CardMedia, CardStatus } from "@src/components/Card";
18
+ import {
19
+ countMissingScreenshots,
20
+ getScreenshotUrl,
21
+ getSharedSliceLibraryName,
22
+ } from "@src/domain/slice";
23
+ import {
24
+ StatusBadge,
25
+ type StatusBadgeProps,
26
+ } from "@src/features/changes/StatusBadge";
27
+ import { SLICES_CONFIG } from "@src/features/slices/slicesConfig";
28
+ import { AddPhotoAlternateIcon } from "@src/icons/AddPhotoAlternateIcon";
29
+
30
+ type SharedSliceViewCardProps = {
31
+ action:
32
+ | { type: "menu"; onRemove: () => void; onRename: () => void }
33
+ | { type: "remove"; onRemove: () => void }
34
+ | ({ type: "status" } & Omit<StatusBadgeProps, "modelType">);
35
+ isDeletedSlice: boolean;
36
+ onUpdateScreenshot: (() => void) | undefined;
37
+ slice: ComponentUI;
38
+ };
39
+
40
+ export const SharedSliceViewCard: FC<SharedSliceViewCardProps> = ({
41
+ action,
42
+ isDeletedSlice,
43
+ onUpdateScreenshot,
44
+ slice,
45
+ }) => {
46
+ const defaultVariation = ComponentUI.variation(slice);
47
+ if (!defaultVariation) return null;
48
+ const href = SLICES_CONFIG.getBuilderPagePathname({
49
+ libraryName: slice.href,
50
+ sliceName: slice.model.name,
51
+ variationId: defaultVariation.id,
52
+ });
53
+ const src = getScreenshotUrl(slice, defaultVariation);
54
+ const canUpdateScreenshot = !!onUpdateScreenshot && !isDeletedSlice;
55
+ return (
56
+ <Card
57
+ {...(href !== undefined && !isDeletedSlice
58
+ ? { component: Link, href, interactive: true }
59
+ : { interactive: false })}
60
+ >
61
+ {src !== undefined ? (
62
+ <CardMedia
63
+ overlay={
64
+ canUpdateScreenshot ? (
65
+ <Box alignItems="center" justifyContent="center">
66
+ <UpdateScreenshotButton onClick={onUpdateScreenshot} />
67
+ </Box>
68
+ ) : undefined
69
+ }
70
+ src={src}
71
+ />
72
+ ) : (
73
+ <CardMedia component="div">
74
+ <Box
75
+ alignItems="center"
76
+ flexDirection="column"
77
+ gap={8}
78
+ justifyContent="center"
79
+ >
80
+ <Text color="grey11" component="span">
81
+ No screenshot available
82
+ </Text>
83
+ {canUpdateScreenshot ? (
84
+ <UpdateScreenshotButton onClick={onUpdateScreenshot} />
85
+ ) : undefined}
86
+ </Box>
87
+ </CardMedia>
88
+ )}
89
+ <CardFooter
90
+ action={
91
+ action.type === "menu" ? (
92
+ <DropdownMenu modal>
93
+ <DropdownMenuTrigger>
94
+ <IconButton icon="moreVert" />
95
+ </DropdownMenuTrigger>
96
+ <DropdownMenuContent align="end">
97
+ <DropdownMenuItem
98
+ onSelect={action.onRename}
99
+ startIcon={<Icon name="edit" />}
100
+ >
101
+ Rename
102
+ </DropdownMenuItem>
103
+ <DropdownMenuItem
104
+ color="tomato"
105
+ onSelect={action.onRemove}
106
+ startIcon={<Icon name="delete" />}
107
+ >
108
+ Delete
109
+ </DropdownMenuItem>
110
+ </DropdownMenuContent>
111
+ </DropdownMenu>
112
+ ) : action.type === "remove" ? (
113
+ <IconButton icon="close" onClick={action.onRemove} />
114
+ ) : (
115
+ <StatusBadge
116
+ authStatus={action.authStatus}
117
+ isOnline={action.isOnline}
118
+ modelStatus={action.modelStatus}
119
+ modelType="Slice"
120
+ />
121
+ )
122
+ }
123
+ subtitle={getSharedSliceLibraryName(slice)}
124
+ title={slice.model.name}
125
+ />
126
+ {canUpdateScreenshot && countMissingScreenshots(slice) > 0 ? (
127
+ <CardStatus>Missing screenshot</CardStatus>
128
+ ) : undefined}
129
+ </Card>
130
+ );
131
+ };
132
+
133
+ type UpdateScreenshotButtonProps = {
134
+ onClick: () => void;
135
+ };
136
+
137
+ const UpdateScreenshotButton: FC<UpdateScreenshotButtonProps> = (props) => (
138
+ <Button
139
+ onClick={props.onClick}
140
+ renderStartIcon={() => (
141
+ <AddPhotoAlternateIcon color={tokens.color.greyLight11} />
142
+ )}
143
+ variant="secondary"
144
+ >
145
+ Update screenshot
146
+ </Button>
147
+ );
@@ -1,6 +1,6 @@
1
1
  import { ChangesPushSagaPayload } from ".";
2
2
  import { telemetry } from "@src/apiClient";
3
- import { countMissingScreenshots } from "@src/utils/screenshots/missing";
3
+ import { countMissingScreenshots } from "@src/domain/slice";
4
4
  import { ModelStatus } from "@lib/models/common/ModelStatus";
5
5
 
6
6
  type trackingParameters = ChangesPushSagaPayload & { startTime: number };
@@ -302,7 +302,7 @@ describe("Custom Type Builder", () => {
302
302
  const user = userEvent.setup();
303
303
  await user.click(screen.getByText("Select existing"));
304
304
 
305
- const slicesToSelect = screen.getAllByTestId("slicezone-modal-item");
305
+ const slicesToSelect = screen.getAllByTestId("shared-slice-selection-card");
306
306
 
307
307
  for (const elem of slicesToSelect) {
308
308
  // eslint-disable-next-line @typescript-eslint/await-thenable
@@ -31,7 +31,7 @@ describe("slices", () => {
31
31
  mockRouter.setCurrentUrl("/slices");
32
32
  });
33
33
 
34
- test("When user creates a slice it should send a tracking event", async (ctx) => {
34
+ test.skip("When user creates a slice it should send a tracking event", async (ctx) => {
35
35
  const adapter = createTestPlugin({
36
36
  setup: ({ hook }) => {
37
37
  hook("slice:create", () => void 0);
@@ -206,7 +206,7 @@ describe("slices", () => {
206
206
  );
207
207
  });
208
208
 
209
- test("if creation fails it sohuld not send the tracking event", async (ctx) => {
209
+ test.skip("if creation fails it sohuld not send the tracking event", async (ctx) => {
210
210
  const adapter = createTestPlugin({
211
211
  setup: ({ hook }) => {
212
212
  hook("slice:create", () => {
@@ -1,71 +0,0 @@
1
- import React from "react";
2
- import { Box, Flex } from "theme-ui";
3
- import { MenuOption } from ".";
4
-
5
- const MenuItem: React.FunctionComponent<MenuOption> = ({
6
- displayName,
7
- onClick,
8
- dataCy,
9
- }) => {
10
- return (
11
- <Box
12
- sx={{
13
- py: 2,
14
- px: 3,
15
- cursor: "pointer",
16
- fontSize: "14px",
17
- borderRadius: 0,
18
- ":hover": {
19
- bg: "hoverBackground",
20
- },
21
- }}
22
- onClick={onClick}
23
- data-cy={dataCy}
24
- >
25
- {displayName}
26
- </Box>
27
- );
28
- };
29
-
30
- export const KebabMenuList: React.FunctionComponent<{
31
- menuOptions: MenuOption[];
32
- closeMenu: () => void;
33
- dataCy?: string;
34
- }> = ({ menuOptions, closeMenu, dataCy }) => {
35
- return (
36
- <Box
37
- data-cy={dataCy}
38
- sx={{
39
- py: 1,
40
- flexDirection: "column",
41
- backgroundColor: "headSection",
42
- overflow: "auto",
43
- display: "flex",
44
- borderRadius: "6px",
45
- border: (t) => `1px solid ${String(t.colors?.darkBorder)}`,
46
- boxShadow: "0 10px 10px rgba(0, 0, 0, 0.05)",
47
- maxHeight: 340,
48
- minWidth: 120,
49
- maxWidth: 350,
50
- color: "text",
51
- }}
52
- >
53
- <Flex sx={{ p: 0, flexDirection: "column" }}>
54
- {menuOptions.map((option) => {
55
- return (
56
- <MenuItem
57
- key={option.displayName}
58
- displayName={option.displayName}
59
- onClick={(event) => {
60
- closeMenu();
61
- event.preventDefault();
62
- option.onClick(event);
63
- }}
64
- dataCy={option.dataCy}
65
- />
66
- );
67
- })}
68
- </Flex>
69
- </Box>
70
- );
71
- };