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
2 changes: 2 additions & 0 deletions packages/api-v4/src/delivery/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export const streamStatus = {
Active: 'active',
Deactivating: 'deactivating',
Failed: 'failed',
Inactive: 'inactive',
Provisioning: 'provisioning',
} as const;
Expand Down
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-13551-added-1774974854479.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Added
---

New stream statuses - deactivating, failed ([#13551](https://github.com/linode/manager/pull/13551))
10 changes: 10 additions & 0 deletions packages/manager/src/features/Delivery/Shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ export const streamStatusOptions: AutocompleteOption[] = [
label: 'Active',
pendoId: 'Logs Delivery Streams-Status Active',
},
{
value: streamStatus.Deactivating,
label: 'Deactivating',
pendoId: 'Logs Delivery Streams-Status Deactivating',
},
{
value: streamStatus.Failed,
label: 'Failed',
pendoId: 'Logs Delivery Streams-Status Failed',
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.

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.

Added

},
{
value: streamStatus.Inactive,
label: 'Inactive',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface StreamActionMenuProps extends StreamHandlers {

export const StreamActionMenu = (props: StreamActionMenuProps) => {
const { stream, onDelete, onDisableOrEnable, onEdit } = props;
const { status, label } = stream;

const menuActions: Action[] = [
{
Expand All @@ -30,9 +31,12 @@ export const StreamActionMenu = (props: StreamActionMenuProps) => {
onClick: () => {
onDisableOrEnable(stream);
},
title: stream.status === streamStatus.Active ? 'Deactivate' : 'Activate',
pendoId: `Logs Delivery Streams-${stream.status === streamStatus.Active ? 'Deactivate' : 'Activate'}`,
disabled: stream.status === streamStatus.Provisioning,
title: status === streamStatus.Active ? 'Deactivate' : 'Activate',
pendoId: `Logs Delivery Streams-${status === streamStatus.Active ? 'Deactivate' : 'Activate'}`,
disabled:
status === streamStatus.Deactivating ||
status === streamStatus.Failed ||
status === streamStatus.Provisioning,
},
{
onClick: () => {
Expand All @@ -46,7 +50,7 @@ export const StreamActionMenu = (props: StreamActionMenuProps) => {
return (
<ActionMenu
actionsList={menuActions}
ariaLabel={`Action menu for Stream ${stream.label}`}
ariaLabel={`Action menu for Stream ${label}`}
pendoId="Logs Delivery Streams-Action Menu"
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { streamStatus } from '@linode/api-v4';
import {
screen,
waitFor,
Expand Down Expand Up @@ -241,47 +242,63 @@
});
});

describe('and stream has status: provisioning', () => {
it('should have disabled Edit Stream button and show info tooltip', async () => {
server.use(
http.get('*/monitor/streams/destinations', () => {
return HttpResponse.json(makeResourcePage(mockDestinations));
}),
http.get(`*/monitor/streams/${streamId}`, () => {
return HttpResponse.json({
...mockStream,
status: 'provisioning',
});
})
);

renderWithThemeAndHookFormContext({
component: <StreamEdit />,
const blockingStatuses = [
streamStatus.Deactivating,
streamStatus.Failed,
streamStatus.Provisioning,
];

describe.each(blockingStatuses)(
'and stream has status: %status',
(status) => {

Check warning on line 253 in packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.test.tsx

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Refactor this code to not nest functions more than 4 levels deep. Raw Output: {"ruleId":"sonarjs/no-nested-functions","severity":1,"message":"Refactor this code to not nest functions more than 4 levels deep.","line":253,"column":22,"nodeType":null,"endLine":253,"endColumn":24}
it('should have disabled Edit Stream button and show info tooltip', async () => {
server.use(
http.get('*/monitor/streams/destinations', () => {
return HttpResponse.json(
makeResourcePage(mockDestinations)
);
}),
http.get(`*/monitor/streams/${streamId}`, () => {
return HttpResponse.json({
...mockStream,
status,
});
})
);

renderWithThemeAndHookFormContext({
component: <StreamEdit />,
});
const loadingElement = screen.queryByTestId(loadingTestId);
await waitForElementToBeRemoved(loadingElement);

const editStreamButton = screen.getByRole('button', {
name: saveStreamButtonText,
});

// Edit stream button should be disabled
expect(editStreamButton).toBeDisabled();

// Edit stream
await userEvent.hover(editStreamButton);
await screen.findByRole('tooltip');

screen.getByText((content) =>
content.includes(
`You cannot save changes while the stream status is ${status}`
)
);

const disabledButtonTooltip = screen.getByText((content) =>
content.includes(
`You cannot save changes while the stream status is ${status}`
)
);

expect(disabledButtonTooltip).toBeInTheDocument();
});
const loadingElement = screen.queryByTestId(loadingTestId);
await waitForElementToBeRemoved(loadingElement);

const editStreamButton = screen.getByRole('button', {
name: saveStreamButtonText,
});

// Edit stream button should be disabled
expect(editStreamButton).toBeDisabled();

// Edit stream
await userEvent.hover(editStreamButton);

await waitFor(() => {
expect(screen.getByRole('tooltip')).toBeInTheDocument();
});

const disabledButtonTooltip = screen.getByText(
'You cannot save changes while the stream is provisioning.'
);

expect(disabledButtonTooltip).toBeInTheDocument();
});
});
}
);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,23 @@ export const StreamForm = (props: StreamFormProps) => {
control,
name: 'stream.status',
});

const isStreamStatusBlocking =
!!selectedStreamStatus &&
(
[
streamStatus.Provisioning,
streamStatus.Deactivating,
streamStatus.Failed,
] as StreamStatus[]
).includes(selectedStreamStatus);

const submitButtonTooltip = useMemo(
() =>
selectedStreamStatus === streamStatus.Provisioning
? 'You cannot save changes while the stream is provisioning.'
isStreamStatusBlocking
? `You cannot save changes while the stream status is ${selectedStreamStatus}`
: undefined,
[selectedStreamStatus]
[isStreamStatusBlocking, selectedStreamStatus]
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.

[selectedStreamStatus] should be enough.
isStreamStatusBlocking depends on selectedStreamStatus change.

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.

It must be included in array, cause both are used in the useMemo.

);

useEffect(() => {
Expand Down Expand Up @@ -212,8 +223,7 @@ export const StreamForm = (props: StreamFormProps) => {
<Grid size={{ lg: 3, md: 12, sm: 12, xs: 12 }}>
<FormSubmitBar
blockSubmit={
selectedStreamStatus === streamStatus.Provisioning ||
!selectedDestinations?.length
isStreamStatusBlocking || !selectedDestinations?.length
}
connectionTested={destinationVerified}
destinationType={destination?.type}
Expand Down
14 changes: 11 additions & 3 deletions packages/manager/src/features/Delivery/Streams/StreamTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ interface StreamTableRowProps extends StreamHandlers {
export const StreamTableRow = React.memo((props: StreamTableRowProps) => {
const { stream, onDelete, onDisableOrEnable, onEdit } = props;
const { id, status } = stream;
const iconStatus = (
['active', 'error', 'inactive'].includes(status) ? status : 'other'
) as Status;
const iconStatus = ((): Status => {
if (status === 'failed') return 'error';
if (['active', 'error', 'inactive'].includes(status)) {
return status as Status;
}
return 'other';
})();

return (
<TableRow key={id}>
Expand Down Expand Up @@ -72,6 +76,10 @@ const humanizeStreamStatus = (status: StreamStatus) => {
switch (status) {
case 'active':
return 'Active';
case 'deactivating':
return 'Deactivating';
case 'failed':
return 'Failed';
case 'inactive':
return 'Inactive';
case 'provisioning':
Expand Down
14 changes: 7 additions & 7 deletions packages/validation/src/delivery.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,9 @@ const streamSchemaBase = object({
.min(3, 'Stream name must have at least 3 characters.')
.max(maxLength, maxLengthMessage)
.required('Stream name is required.'),
status: mixed<'active' | 'inactive' | 'provisioning'>().oneOf([
'active',
'inactive',
'provisioning',
]),
status: mixed<
'active' | 'deactivating' | 'failed' | 'inactive' | 'provisioning'
>().oneOf(['active', 'deactivating', 'failed', 'inactive', 'provisioning']),
type: string()
.oneOf(['audit_logs', 'lke_audit_logs'])
.required('Stream type is required.'),
Expand All @@ -372,8 +370,10 @@ export const createStreamSchema = streamSchemaBase;
export const updateStreamSchema = streamSchemaBase
.omit(['type'])
.shape({
status: mixed<'active' | 'inactive' | 'provisioning'>()
.oneOf(['active', 'inactive', 'provisioning'])
status: mixed<
'active' | 'deactivating' | 'failed' | 'inactive' | 'provisioning'
>()
.oneOf(['active', 'deactivating', 'failed', 'inactive', 'provisioning'])
.required(),
details: lazy((value) => {
if (
Expand Down
Loading