Skip to content

Commit 5902fbb

Browse files
upcoming: [UIE-9410] - Create Share Group: Implement the Images select table (#13567)
* Added missing padding around the Managed dashboard card * changed spacing to spacingFunction * Implement the images multi-select table * Remove unnecessary async statement * Improve the image select component * Rename variable for clarity * Added changeset: Private Image Sharing: implement the images select table in the create share groups page * Update packages/manager/.changeset/pr-13567-upcoming-features-1775674749388.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> * Fix bug with the image description in the image payload * Add pendoId support for the landing header * Add loading state for the submit button * Update constants.ts --------- Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com>
1 parent 7f35a94 commit 5902fbb

File tree

12 files changed

+176
-61
lines changed

12 files changed

+176
-61
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Private Image Sharing: implement Select Images table on Share Group Create page ([#13567](https://github.com/linode/manager/pull/13567))

packages/manager/src/components/Breadcrumb/Breadcrumb.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export interface BreadcrumbProps {
4040
* A string representation of the path of a resource. Each crumb is separated by a `/` character.
4141
*/
4242
pathname: string;
43+
/**
44+
* A string that can be used to set a custom Pendo ID for the breadcrumb for tracking purposes.
45+
*/
46+
pendoId?: string;
4347
/**
4448
* A number indicating the position of the crumb to remove. Not zero indexed.
4549
*/
@@ -65,6 +69,7 @@ export const Breadcrumb = (props: BreadcrumbProps) => {
6569
labelTitle,
6670
onEditHandlers,
6771
pathname,
72+
pendoId,
6873
removeCrumbX,
6974
sx,
7075
} = props;
@@ -91,6 +96,7 @@ export const Breadcrumb = (props: BreadcrumbProps) => {
9196
<StyledRootDiv
9297
sx={{ ...(hasError && { marginBottom: (theme) => theme.spacing(3) }) }}
9398
{...breadcrumbDataAttrs}
99+
data-pendo-id={pendoId}
94100
>
95101
<StyledPreContainerDiv
96102
sx={{

packages/manager/src/components/ImageSelect/ImageSelectTable.tsx

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ import type {
4545
} from './constants';
4646
import type { Filter, Image } from '@linode/api-v4';
4747
import type { LinkProps } from '@tanstack/react-router';
48+
import type { IMAGE_SELECT_TABLE_SHARE_GROUP_CREATE_PENDO_IDS } from 'src/components/ImageSelect/constants';
49+
50+
type SelectionMode = 'multi' | 'single';
4851

4952
interface Props {
5053
/**
@@ -56,6 +59,7 @@ interface Props {
5659
* Error message to display above the table, e.g. from form validation.
5760
*/
5861
errorText?: string;
62+
5963
/**
6064
* Determines whether additional filtering of images should be applied, typically if there is a StackScript selected.
6165
*/
@@ -69,12 +73,18 @@ interface Props {
6973
*/
7074
pendoIDs:
7175
| typeof IMAGE_SELECT_TABLE_LINODE_CREATE_PENDO_IDS
72-
| typeof IMAGE_SELECT_TABLE_LINODE_REBUILD_PENDO_IDS;
76+
| typeof IMAGE_SELECT_TABLE_LINODE_REBUILD_PENDO_IDS
77+
| typeof IMAGE_SELECT_TABLE_SHARE_GROUP_CREATE_PENDO_IDS;
7378
queryParamsPrefix?: string;
7479
/**
75-
* The ID of the currently selected image.
80+
* The IDs of the currently selected images, when using multi-select mode with checkboxes.
7681
*/
77-
selectedImageId?: null | string;
82+
selectedImageIds: string[];
83+
/**
84+
* Whether this table should use single-select mode with radio buttons, or multi-select mode with checkboxes.
85+
* The default is single select.
86+
*/
87+
selectionMode: SelectionMode;
7888
}
7989

8090
type OptionType = { label: string; value: string };
@@ -87,7 +97,8 @@ export const ImageSelectTable = (props: Props) => {
8797
onSelect,
8898
pendoIDs,
8999
queryParamsPrefix,
90-
selectedImageId,
100+
selectionMode,
101+
selectedImageIds,
91102
} = props;
92103

93104
const theme = useTheme();
@@ -261,29 +272,31 @@ export const ImageSelectTable = (props: Props) => {
261272
<Hidden lgDown>
262273
<TableHeaderCell>Replicated in</TableHeaderCell>
263274
</Hidden>
264-
<Hidden smDown>
265-
<TableHeaderCell
266-
style={{ whiteSpace: 'nowrap', ...TABLE_CELL_BASE_STYLE }}
267-
>
268-
<Stack alignItems="center" direction="row">
269-
Share Group
270-
<TooltipIcon
271-
data-pendo-id={pendoIDs.shareGroupInfoIcon}
272-
status="info"
273-
sxTooltipIcon={{
274-
padding: '4px',
275-
}}
276-
text={SHARE_GROUP_COLUMN_HEADER_TOOLTIP}
277-
tooltipPosition="right"
278-
/>
279-
</Stack>
280-
</TableHeaderCell>
281-
</Hidden>
275+
{selectionMode === 'single' && (
276+
<Hidden smDown>
277+
<TableHeaderCell
278+
style={{ whiteSpace: 'nowrap', ...TABLE_CELL_BASE_STYLE }}
279+
>
280+
<Stack alignItems="center" direction="row">
281+
Share Group
282+
<TooltipIcon
283+
data-pendo-id={pendoIDs.shareGroupInfoIcon}
284+
status="info"
285+
sxTooltipIcon={{
286+
padding: '4px',
287+
}}
288+
text={SHARE_GROUP_COLUMN_HEADER_TOOLTIP}
289+
tooltipPosition="right"
290+
/>
291+
</Stack>
292+
</TableHeaderCell>
293+
</Hidden>
294+
)}
282295
<Hidden lgDown>
283296
<TableHeaderCell
284297
style={{ whiteSpace: 'nowrap', ...TABLE_CELL_BASE_STYLE }}
285298
>
286-
Size
299+
{selectionMode === 'single' ? 'Size' : 'Original Image'}
287300
</TableHeaderCell>
288301
</Hidden>
289302
<TableHeaderCell
@@ -324,7 +337,8 @@ export const ImageSelectTable = (props: Props) => {
324337
onSelect={() => onSelect(image)}
325338
pendoIDs={pendoIDs}
326339
regions={regions ?? []}
327-
selected={image.id === selectedImageId}
340+
selectedImageIds={selectedImageIds}
341+
selectionMode={selectionMode}
328342
timezone={profile?.timezone}
329343
/>
330344
))}

packages/manager/src/components/ImageSelect/ImageSelectTableRow.tsx

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,31 @@ import type {
2626
} from './constants';
2727
import type { Image, ImageRegion, Region } from '@linode/api-v4';
2828
import type { Theme } from '@linode/ui';
29+
import type { IMAGE_SELECT_TABLE_SHARE_GROUP_CREATE_PENDO_IDS } from 'src/components/ImageSelect/constants';
2930

3031
interface Props {
3132
image: Image;
32-
onSelect: () => void;
33+
onSelect?: () => void;
3334
pendoIDs:
3435
| typeof IMAGE_SELECT_TABLE_LINODE_CREATE_PENDO_IDS
35-
| typeof IMAGE_SELECT_TABLE_LINODE_REBUILD_PENDO_IDS;
36+
| typeof IMAGE_SELECT_TABLE_LINODE_REBUILD_PENDO_IDS
37+
| typeof IMAGE_SELECT_TABLE_SHARE_GROUP_CREATE_PENDO_IDS;
3638
regions: Region[];
37-
selected: boolean;
39+
selectedImageIds: string[];
40+
selectionMode: 'multi' | 'single';
3841
timezone?: string;
3942
}
4043

4144
export const ImageSelectTableRow = (props: Props) => {
42-
const { image, onSelect, pendoIDs, regions, selected, timezone } = props;
45+
const {
46+
image,
47+
onSelect,
48+
pendoIDs,
49+
regions,
50+
selectedImageIds,
51+
timezone,
52+
selectionMode,
53+
} = props;
4354

4455
const {
4556
capabilities,
@@ -91,16 +102,27 @@ export const ImageSelectTableRow = (props: Props) => {
91102
</StyledFormattedRegionList>
92103
);
93104

105+
const selected = selectedImageIds.includes(id);
94106
return (
95-
<TableRow key={id} rowborder>
107+
<TableRow
108+
key={id}
109+
rowborder
110+
select={onSelect}
111+
selectable={selectionMode === 'multi'}
112+
selected={selected}
113+
>
96114
<TableCell style={{ ...TABLE_CELL_BASE_STYLE }}>
97-
<FormControlLabel
98-
checked={selected}
99-
control={<Radio />}
100-
label={label}
101-
onChange={onSelect}
102-
sx={{ gap: 2 }}
103-
/>
115+
{selectionMode === 'single' ? (
116+
<FormControlLabel
117+
checked={selected}
118+
control={<Radio />}
119+
label={label}
120+
onChange={onSelect}
121+
sx={{ gap: 2 }}
122+
/>
123+
) : (
124+
label
125+
)}
104126
{type === 'manual' && capabilities.includes('cloud-init') && (
105127
<TooltipIcon
106128
data-pendo-id={pendoIDs.metadataSupportedIcon}
@@ -133,17 +155,19 @@ export const ImageSelectTableRow = (props: Props) => {
133155
/>
134156
</TableCell>
135157
</Hidden>
136-
<Hidden smDown>
137-
<TableCell
138-
style={{
139-
whiteSpace: 'nowrap',
140-
paddingLeft: matchesLgDown ? '58px' : undefined,
141-
...TABLE_CELL_BASE_STYLE,
142-
}}
143-
>
144-
{getShareGroupDisplay()}
145-
</TableCell>
146-
</Hidden>
158+
{selectionMode === 'single' && (
159+
<Hidden smDown>
160+
<TableCell
161+
style={{
162+
whiteSpace: 'nowrap',
163+
paddingLeft: matchesLgDown ? '58px' : undefined,
164+
...TABLE_CELL_BASE_STYLE,
165+
}}
166+
>
167+
{getShareGroupDisplay()}
168+
</TableCell>
169+
</Hidden>
170+
)}
147171
<Hidden lgDown>
148172
<TableCell style={{ whiteSpace: 'nowrap', ...TABLE_CELL_BASE_STYLE }}>
149173
{getSizeDisplay()}

packages/manager/src/components/ImageSelect/constants.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,18 @@ export const IMAGE_SELECT_TABLE_LINODE_REBUILD_PENDO_IDS = {
2222
replicatedRegionPopover: 'Linodes Rebuild Images-Replicated in',
2323
shareGroupInfoIcon: 'Linodes Rebuild Images-Share Group info icon',
2424
};
25+
26+
export const IMAGE_SELECT_TABLE_SHARE_GROUP_CREATE_PENDO_IDS = {
27+
searchImagesBar: 'Share Groups Create Images-Search click',
28+
tagFilterSelect: 'Share Groups Create Images-Filter by Tag click',
29+
regionFilterSelect: 'Share Groups Create Images-Filter by Region click',
30+
metadataSupportedIcon: 'Share Groups Create Images-Metadata Supported icon',
31+
replicatedRegionPopover: 'Share Groups Create Images-Replicated in',
32+
shareGroupInfoIcon: 'Share Groups Create Images-Share Group info icon',
33+
createImageLink: 'Share Groups Create Images-Create Image Link',
34+
uploadImageLink: 'Share Groups Create Images-Upload Image Link',
35+
imageCheckbox: 'Share Groups Create Images-Image Checkbox',
36+
pageSizeSelect: 'Share Groups Create Images-Page Size Select',
37+
previousPageButton: 'Share Groups Create Images-Previous Page Button',
38+
nextPageButton: 'Share Groups Create Images-Next Page Button',
39+
};

packages/manager/src/components/LandingHeader/LandingHeader.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface LandingHeaderProps {
2929
onButtonClick?: () => void;
3030
onButtonKeyPress?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;
3131
onDocsClick?: () => void;
32+
pendoId?: string;
3233
removeCrumbX?: number | number[];
3334
shouldHideDocsAndCreateButtons?: boolean;
3435
spacingBottom?: 0 | 4 | 16 | 24;
@@ -46,6 +47,7 @@ export const LandingHeader = ({
4647
breadcrumbProps,
4748
buttonDataAttrs,
4849
createButtonText,
50+
pendoId,
4951
disabledBreadcrumbEditButton,
5052
disabledCreateButton,
5153
docsLabel,
@@ -98,6 +100,7 @@ export const LandingHeader = ({
98100
{...breadcrumbDataAttrs}
99101
{...breadcrumbProps}
100102
disabledBreadcrumbEditButton={disabledBreadcrumbEditButton}
103+
pendoId={pendoId}
101104
/>
102105
</Grid>
103106
{!shouldHideDocsAndCreateButtons && (

packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,4 @@ export const StyledImageTableContainer = styled(Box, {
3737
'& cds-table-row:last-child:not([rowborder])': {
3838
borderBottom: `1px solid ${theme.tokens.component.Table.Row.Border}`,
3939
},
40-
41-
'& cds-table-header-cell, & cds-table-cell': {
42-
boxSizing: 'border-box',
43-
},
4440
}));

0 commit comments

Comments
 (0)