Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Add new maintenance policy icons to linode rows ([#12398](https://github.com/linode/manager/pull/12398))
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const useStyles = makeStyles()(() => ({
export type MaintenanceTableType =
| 'completed'
| 'in progress'
| 'pending' // TODO VM & Host Maintenance: Remove pending type after GA
| 'pending'
| 'upcoming';

interface Props {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export const PENDING_MAINTENANCE_FILTER = Object.freeze({
status: { '+or': ['pending', 'started', 'scheduled'] },
});

export const PENDING_AND_IN_PROGRESS_MAINTENANCE_FILTER = Object.freeze({
status: { '+or': ['pending', 'started', 'scheduled', 'in-progress'] },
});

export const PLATFORM_MAINTENANCE_TYPE =
'security_reboot_maintenance_scheduled';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ export const StyledMaintenanceTableCell = styled(TableCell, {
minWidth: 200,
},
},
'& button': {
color: theme.textColors.linkActiveLight,
padding: '0 6px',
position: 'relative',
},

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These maintenance styles are now controlled by ui-TooltipIcon in the theme

[theme.breakpoints.up('md')]: {
width: '20%',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { useTypeQuery } from '@linode/queries';
import { Tooltip, TooltipIcon, Typography } from '@linode/ui';
import {
LoadFailureIcon as MaintenanceActiveIcon,
CalendarIcon as MaintenancePendingIcon,
CalendarScheduledIcon as MaintenanceScheduledIcon,
Tooltip,
TooltipIcon,
Typography,
} from '@linode/ui';
import { Hidden } from '@linode/ui';
import { formatStorageUnits, getFormattedStatus } from '@linode/utilities';
import * as React from 'react';
Expand Down Expand Up @@ -32,6 +39,30 @@ import type { LinodeHandlers } from '../LinodesLanding';
import type { SxProps, Theme } from '@mui/material/styles';
import type { LinodeWithMaintenance } from 'src/utilities/linodes';

const statusTooltipIcons = {
scheduled: <MaintenanceScheduledIcon />,
active: <MaintenanceActiveIcon />,
pending: <MaintenancePendingIcon />,
};

interface MaintenanceTextProps {
isOpened?: boolean;
maintenanceStartTime: string;
}

const MaintenanceText = ({
isOpened = false,
maintenanceStartTime,
}: MaintenanceTextProps) => {
return (
<>
This Linode&rsquo;s maintenance window {isOpened ? 'opened' : 'opens'} at{' '}
{maintenanceStartTime}
{!isOpened && <>. For more information, see your open support tickets</>}.
</>
);
};

interface Props extends LinodeWithMaintenance {
handlers: LinodeHandlers;
}
Expand Down Expand Up @@ -61,22 +92,12 @@ export const LinodeRow = (props: Props) => {

const isBareMetalInstance = linodeType?.class === 'metal';

const loading = linodeInTransition(status, recentEvent);
const isTransitioning = linodeInTransition(status, recentEvent);

const parsedMaintenanceStartTime = parseMaintenanceStartTime(
maintenance?.when
maintenance?.start_time || maintenance?.when

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @hkhalil-akamai left maintenance?.when to be backward compatible during beta. Moving forward we'll just need the new start_time field.

);

const MaintenanceText = () => {
return (
<>
This Linode&rsquo;s maintenance window opens at{' '}
{parsedMaintenanceStartTime}. For more information, see your{' '}
<Link to="/support/tickets/open">open support tickets.</Link>
</>
);
};

const iconStatus = getLinodeIconStatus(status);

const [isHovered, setIsHovered] = React.useState(false);
Expand All @@ -89,6 +110,12 @@ export const LinodeRow = (props: Props) => {
setIsHovered(false);
}, []);

const isPendingOrScheduled =
maintenance?.status === 'pending' || maintenance?.status === 'scheduled';

const isInProgress =
maintenance?.status === 'started' || maintenance?.status === 'in-progress';

return (
<TableRow
data-qa-linode={label}
Expand All @@ -105,36 +132,57 @@ export const LinodeRow = (props: Props) => {
<StyledMaintenanceTableCell
data-qa-status
maintenance={Boolean(maintenance)}
noWrap

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're ok with table possibly scrolling

statusCell
>
{!maintenance ? (
loading ? (
<>
<StatusIcon status={iconStatus} />
<StyledButton onClick={notificationContext.openMenu}>
<ProgressDisplay
progress={getProgressOrDefault(recentEvent)}
sx={{ display: 'inline-block' }}
text={transitionText(status, id, recentEvent)}
/>
</StyledButton>
</>
) : (
<>
<StatusIcon status={iconStatus} />
{getFormattedStatus(status)}
</>
)
) : (
<div style={{ alignItems: 'center', display: 'flex' }}>
<strong>Maintenance Scheduled</strong>
<TooltipIcon
status="help"
sx={{ tooltip: { maxWidth: 300 } }}
text={<MaintenanceText />}
tooltipPosition="top"
<StatusIcon status={iconStatus} />
{!isTransitioning && getFormattedStatus(status)}
{isTransitioning && (
<StyledButton onClick={notificationContext.openMenu}>
<ProgressDisplay
progress={getProgressOrDefault(recentEvent)}
sx={{ display: 'inline-block' }}
text={transitionText(status, id, recentEvent)}
/>
</div>
</StyledButton>
)}
{isInProgress && (
<TooltipIcon
className="ui-TooltipIcon ui-TooltipIcon-isActive"
icon={statusTooltipIcons.active}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit odd to me that in-progress is a red exclamation icon; makes it seem like the action errored out. Should we use the warning icon here instead?

context: #12348

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe even use the in-progress spinning icon in the notification bell?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - In this case it is "Emergency" maintenance hence the red color. UX did do a design permutation with the warning icon and based on review with PM and SA. They leaned towards an icon that represented "progress" in this case.

I agree that there may be a better icon (perhaps the animated autorenew icon we use for events. Either way, I think this is something we can revisit during beta.

status="other"
sx={{ tooltip: { maxWidth: 300 } }}
text={
<MaintenanceText
isOpened
maintenanceStartTime={parsedMaintenanceStartTime}
/>
}
tooltipPosition="top"
/>
)}
{isPendingOrScheduled && (
<TooltipIcon
className="ui-TooltipIcon"
icon={
maintenance.status === 'pending'
? statusTooltipIcons.pending
: statusTooltipIcons.scheduled
}
status="other"
sx={{ tooltip: { maxWidth: 300 } }}
text={
maintenance.status === 'pending' ? (
"This Linode's maintenance window is pending."
) : (
<MaintenanceText
isOpened={false}
maintenanceStartTime={parsedMaintenanceStartTime}
/>
)
}
tooltipPosition="top"
/>
)}
</StyledMaintenanceTableCell>
<Hidden smDown>
Expand Down
4 changes: 2 additions & 2 deletions packages/manager/src/features/Linodes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useInProgressEvents } from 'src/queries/events/events';
import { addMaintenanceToLinodes } from 'src/utilities/linodes';
import { storage } from 'src/utilities/storage';

import { PENDING_MAINTENANCE_FILTER } from '../Account/Maintenance/utilities';
import { PENDING_AND_IN_PROGRESS_MAINTENANCE_FILTER } from '../Account/Maintenance/utilities';
import { regionFilterOptions } from './LinodesLanding/RegionTypeFilter';
import { linodesInTransition } from './transitions';

Expand Down Expand Up @@ -54,7 +54,7 @@ export const LinodesRoutes = () => {
export const LinodesLandingWrapper = React.memo(() => {
const { data: accountMaintenanceData } = useAllAccountMaintenanceQuery(
{},
PENDING_MAINTENANCE_FILTER
PENDING_AND_IN_PROGRESS_MAINTENANCE_FILTER
);
const flags = useFlags();

Expand Down
14 changes: 12 additions & 2 deletions packages/manager/src/utilities/linodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@ import { useFlags } from 'src/hooks/useFlags';

import type { AccountMaintenance, Linode } from '@linode/api-v4';

export interface Maintenance {
export interface LinodeMaintenance {
start_time: null | string;
status?:
| 'canceled'
| 'completed'
| 'in-progress'
| 'pending'
| 'scheduled'
| 'started';

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding status to the maintenance object we're manually appending to the Linode to make the distinction between pending and scheduled for now.

when: null | string;
}

export interface LinodeWithMaintenance extends Linode {
maintenance?: Maintenance | null;
maintenance?: LinodeMaintenance | null;
}

export const addMaintenanceToLinodes = (
Expand All @@ -29,6 +37,8 @@ export const addMaintenanceToLinodes = (
? {
...thisLinode,
maintenance: {
start_time: foundMaintenance.start_time,
status: foundMaintenance.status,
when: foundMaintenance.when,
},
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/ui": Upcoming Features
---

Add new maintenance policy icons and update TooltipIcon tokens ([#12398](https://github.com/linode/manager/pull/12398))
3 changes: 3 additions & 0 deletions packages/ui/src/assets/icons/calendar-schedule.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/ui/src/assets/icons/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/ui/src/assets/icons/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { default as AlertIcon } from './alert.svg';
export { default as CalendarScheduledIcon } from './calendar-schedule.svg';
export { default as CalendarIcon } from './calendar.svg';
export { default as CheckIcon } from './check.svg';
export { default as CheckboxIcon } from './checkbox.svg';
export { default as CheckboxCheckedIcon } from './checkboxChecked.svg';
Expand All @@ -13,6 +15,7 @@ export { default as ErrorIcon } from './error.svg';
export { default as InfoOutlinedIcon } from './info-outlined.svg';
export { default as InfoIcon } from './info.svg';
export { default as LightBulbIcon } from './lightbulb.svg';
export { default as LoadFailureIcon } from './load-failure.svg';
export { default as PendingIcon } from './pending.svg';
export { default as PlusSignIcon } from './plusSign.svg';
export { default as RadioIcon } from './radio.svg';
Expand Down
6 changes: 6 additions & 0 deletions packages/ui/src/assets/icons/load-failure.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading