Skip to content

Commit

Permalink
feat: add delete button to row action
Browse files Browse the repository at this point in the history
  • Loading branch information
tthvo committed Aug 8, 2024
1 parent b2986cb commit 0cb9ea7
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/app/Recordings/ActiveRecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,7 @@ export const ActiveRecordingRow: React.FC<ActiveRecordingRowProps> = ({
index={index}
recording={recording}
uploadFn={() => context.api.uploadActiveRecordingToGrafana(recording.name)}
deleteFn={() => context.api.deleteRecording(recording.name)}
/>
</Tr>
);
Expand Down
9 changes: 8 additions & 1 deletion src/app/Recordings/ArchivedRecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import { UploadIcon, EllipsisVIcon } from '@patternfly/react-icons';
import { Tbody, Tr, Td, ExpandableRowContent, Table, SortByDirection } from '@patternfly/react-table';
import * as React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Observable, forkJoin, merge, combineLatest } from 'rxjs';
import { Observable, forkJoin, merge, combineLatest, of } from 'rxjs';
import { concatMap, filter, first, map } from 'rxjs/operators';
import { LabelCell } from '../RecordingMetadata/LabelCell';
import { RecordingActions } from './RecordingActions';
Expand Down Expand Up @@ -905,12 +905,19 @@ export const ArchivedRecordingRow: React.FC<ArchivedRecordingRowProps> = ({
recording={recording}
index={index}
uploadFn={() => context.api.uploadArchivedRecordingToGrafanaFromPath(propsDirectory.jvmId, recording.name)}
deleteFn={() => context.api.deleteArchivedRecordingFromPath(propsDirectory.jvmId, recording.name)}
/>
) : (
<RecordingActions
recording={recording}
index={index}
uploadFn={() => context.api.uploadArchivedRecordingToGrafana(sourceTarget, recording.name)}
deleteFn={() => {
context.reports.delete(recording);
return sourceTarget.pipe(
concatMap((t) => (t ? context.api.deleteArchivedRecording(t.connectUrl, recording.name) : of(false))),
);
}}
/>
)}
</Tr>
Expand Down
71 changes: 51 additions & 20 deletions src/app/Recordings/RecordingActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,36 @@ import { Recording, Target } from '@app/Shared/Services/api.types';
import { NotificationsContext } from '@app/Shared/Services/Notifications.service';
import { ServiceContext } from '@app/Shared/Services/Services';
import { useSubscriptions } from '@app/utils/hooks/useSubscriptions';
import { Dropdown, DropdownItem, DropdownList, MenuToggle, MenuToggleElement } from '@patternfly/react-core';
import { EllipsisVIcon } from '@patternfly/react-icons';
import { Divider, Dropdown, DropdownItem, DropdownList, MenuToggle, MenuToggleElement } from '@patternfly/react-core';
import { DivideIcon, EllipsisVIcon } from '@patternfly/react-icons';
import { Td } from '@patternfly/react-table';
import * as React from 'react';
import { Observable } from 'rxjs';
import { first } from 'rxjs/operators';

export interface RowAction {
title: string | React.ReactNode;
key: string;
onClick: () => void;
title?: string | React.ReactNode;
key?: string;
onClick?: () => void;
isSeparator?: boolean;
}

export interface RecordingActionsProps {
index: number;
recording: Recording;
sourceTarget?: Observable<Target>;
uploadFn: () => Observable<boolean>;
deleteFn: () => Observable<boolean>;
}

export const RecordingActions: React.FC<RecordingActionsProps> = (props) => {
export const RecordingActions: React.FC<RecordingActionsProps> = ({
index,
recording,
sourceTarget,
uploadFn,
deleteFn,
...props
}) => {
const context = React.useContext(ServiceContext);
const notifications = React.useContext(NotificationsContext);
const [grafanaEnabled, setGrafanaEnabled] = React.useState(false);
Expand All @@ -55,14 +64,13 @@ export const RecordingActions: React.FC<RecordingActionsProps> = (props) => {
}, [context.api, setGrafanaEnabled, addSubscription]);

const grafanaUpload = React.useCallback(() => {
notifications.info('Upload Started', `Recording "${props.recording.name}" uploading...`);
notifications.info('Upload Started', `Recording "${recording.name}" uploading...`);
addSubscription(
props
.uploadFn()
uploadFn()
.pipe(first())
.subscribe((success) => {
if (success) {
notifications.success('Upload Success', `Recording "${props.recording.name}" uploaded`);
notifications.success('Upload Success', `Recording "${recording.name}" uploaded`);
context.api
.grafanaDashboardUrl()
.pipe(first())
Expand All @@ -73,8 +81,13 @@ export const RecordingActions: React.FC<RecordingActionsProps> = (props) => {
}, [addSubscription, notifications, props, context.api]);

const handleDownloadRecording = React.useCallback(() => {
context.api.downloadRecording(props.recording);
}, [context.api, props.recording]);
context.api.downloadRecording(recording);
}, [context.api, recording]);

const handleDeleteRecording = React.useCallback(
() => addSubscription(deleteFn().subscribe()),
[addSubscription, context.api, recording],
);

const actionItems = React.useMemo(() => {
const actionItems = [
Expand All @@ -91,13 +104,25 @@ export const RecordingActions: React.FC<RecordingActionsProps> = (props) => {
onClick: grafanaUpload,
});
}

actionItems.push(
{
isSeparator: true,
},
{
title: 'Delete',
key: 'delete',
onClick: handleDeleteRecording,
},
);

return actionItems;
}, [handleDownloadRecording, grafanaEnabled, grafanaUpload]);

const onSelect = React.useCallback(
(action: RowAction) => {
setIsOpen(false);
action.onClick();
action.onClick && action.onClick();
},
[setIsOpen],
);
Expand All @@ -118,23 +143,29 @@ export const RecordingActions: React.FC<RecordingActionsProps> = (props) => {
);

return (
<Td isActionCell>
<Td {...props} isActionCell>
<Dropdown
toggle={toggle}
popperProps={{
appendTo: document.body,
position: 'right',
direction: 'down',
}}
aria-label={`${props.recording.name}-actions`}
aria-label={`${recording.name}-actions`}
isOpen={isOpen}
onOpenChange={(isOpen) => setIsOpen(isOpen)}
onOpenChangeKeys={['Escape']}
>
<DropdownList>
{actionItems.map((action) => (
<DropdownItem key={action.key} onClick={() => onSelect(action)} data-quickstart-id={action.key}>
{action.title}
</DropdownItem>
))}
{actionItems.map((action) =>
action.isSeparator ? (
<Divider />
) : (
<DropdownItem key={action.key} onClick={() => onSelect(action)} data-quickstart-id={action.key}>
{action.title}
</DropdownItem>
),
)}
</DropdownList>
</Dropdown>
</Td>
Expand Down
4 changes: 2 additions & 2 deletions src/app/Recordings/RecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const RecordingsTable: React.FC<RecordingsTableProps> = ({
<Bullseye>
<EmptyState>
<EmptyStateHeader
titleText={<>No{tableTitle}</>}
titleText={<>No {tableTitle}</>}
icon={<EmptyStateIcon icon={SearchIcon} />}
headingLevel="h4"
/>
Expand All @@ -109,7 +109,7 @@ export const RecordingsTable: React.FC<RecordingsTableProps> = ({
<Bullseye>
<EmptyState>
<EmptyStateHeader
titleText={<>No{tableTitle}found</>}
titleText={<>No {tableTitle}found</>}
icon={<EmptyStateIcon icon={SearchIcon} />}
headingLevel="h4"
/>
Expand Down

0 comments on commit 0cb9ea7

Please sign in to comment.