Added spinner for notebook delete (#458)

* initial UI for delete published nb spinner

* added notebook delete spinner

* addressed PR comments
This commit is contained in:
Srinath Narayanan 2021-03-02 13:59:10 -08:00 committed by GitHub
parent 4127d0f522
commit b8e9903287
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 139 additions and 89 deletions

View File

@ -13,6 +13,8 @@ import {
LinkBase,
Separator,
TooltipHost,
Spinner,
SpinnerSize,
} from "office-ui-fabric-react";
import * as React from "react";
import { IGalleryItem } from "../../../../Juno/JunoClient";
@ -29,10 +31,14 @@ export interface GalleryCardComponentProps {
onFavoriteClick: () => void;
onUnfavoriteClick: () => void;
onDownloadClick: () => void;
onDeleteClick: () => void;
onDeleteClick: (beforeDelete: () => void, afterDelete: () => void) => void;
}
export class GalleryCardComponent extends React.Component<GalleryCardComponentProps> {
interface GalleryCardComponentState {
isDeletingPublishedNotebook: boolean;
}
export class GalleryCardComponent extends React.Component<GalleryCardComponentProps, GalleryCardComponentState> {
public static readonly CARD_WIDTH = 256;
private static readonly cardImageHeight = 144;
public static readonly cardHeightToWidthRatio =
@ -40,6 +46,14 @@ export class GalleryCardComponent extends React.Component<GalleryCardComponentPr
private static readonly cardDescriptionMaxChars = 80;
private static readonly cardItemGapBig = 10;
private static readonly cardItemGapSmall = 8;
private static readonly cardDeleteSpinnerHeight = 360;
constructor(props: GalleryCardComponentProps) {
super(props);
this.state = {
isDeletingPublishedNotebook: false,
};
}
public render(): JSX.Element {
const cardButtonsVisible = this.props.isFavorite !== undefined || this.props.showDownload || this.props.showDelete;
@ -59,6 +73,17 @@ export class GalleryCardComponent extends React.Component<GalleryCardComponentPr
tokens={{ width: GalleryCardComponent.CARD_WIDTH, childrenGap: 0 }}
onClick={(event) => this.onClick(event, this.props.onClick)}
>
{this.state.isDeletingPublishedNotebook && (
<Card.Item tokens={{ padding: GalleryCardComponent.cardItemGapBig }}>
<Spinner
size={SpinnerSize.large}
label={`Deleting '${cardTitle}'`}
styles={{ root: { height: GalleryCardComponent.cardDeleteSpinnerHeight } }}
/>
</Card.Item>
)}
{!this.state.isDeletingPublishedNotebook && (
<>
<Card.Item tokens={{ padding: GalleryCardComponent.cardItemGapBig }}>
<Persona
imageUrl={this.props.data.isSample && CosmosDBLogo}
@ -109,7 +134,8 @@ export class GalleryCardComponent extends React.Component<GalleryCardComponentPr
</Text>
<span>
{this.props.data.views !== undefined && this.generateIconText("RedEye", this.props.data.views.toString())}
{this.props.data.views !== undefined &&
this.generateIconText("RedEye", this.props.data.views.toString())}
{this.props.data.downloads !== undefined &&
this.generateIconText("Download", this.props.data.downloads.toString())}
{this.props.data.favorites !== undefined &&
@ -141,10 +167,17 @@ export class GalleryCardComponent extends React.Component<GalleryCardComponentPr
this.generateIconButtonWithTooltip("Download", "Download", "left", this.props.onDownloadClick)}
{this.props.showDelete &&
this.generateIconButtonWithTooltip("Delete", "Remove", "right", this.props.onDeleteClick)}
this.generateIconButtonWithTooltip("Delete", "Remove", "right", () =>
this.props.onDeleteClick(
() => this.setState({ isDeletingPublishedNotebook: true }),
() => this.setState({ isDeletingPublishedNotebook: false })
)
)}
</span>
</Card.Section>
)}
</>
)}
</Card>
);
}

View File

@ -666,7 +666,8 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
onFavoriteClick: () => this.favoriteItem(data),
onUnfavoriteClick: () => this.unfavoriteItem(data),
onDownloadClick: () => this.downloadItem(data),
onDeleteClick: () => this.deleteItem(data),
onDeleteClick: (beforeDelete: () => void, afterDelete: () => void) =>
this.deleteItem(data, beforeDelete, afterDelete),
};
return (
@ -710,11 +711,18 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
);
};
private deleteItem = async (data: IGalleryItem): Promise<void> => {
GalleryUtils.deleteItem(this.props.container, this.props.junoClient, data, (item) => {
private deleteItem = async (data: IGalleryItem, beforeDelete: () => void, afterDelete: () => void): Promise<void> => {
GalleryUtils.deleteItem(
this.props.container,
this.props.junoClient,
data,
(item) => {
this.publishedNotebooks = this.publishedNotebooks?.filter((notebook) => item.id !== notebook.id);
this.refreshSelectedTab(item);
});
},
beforeDelete,
afterDelete
);
};
private onPivotChange = (item: PivotItem): void => {

View File

@ -373,7 +373,9 @@ export function deleteItem(
container: Explorer,
junoClient: JunoClient,
data: IGalleryItem,
onComplete: (item: IGalleryItem) => void
onComplete: (item: IGalleryItem) => void,
beforeDelete?: () => void,
afterDelete?: () => void
): void {
if (container) {
trace(Action.NotebooksGalleryClickDelete, ActionModifiers.Mark, { notebookId: data.id });
@ -383,6 +385,9 @@ export function deleteItem(
`Would you like to remove ${data.name} from the gallery?`,
"Remove",
async () => {
if (beforeDelete) {
beforeDelete();
}
const name = data.name;
const notificationId = NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.InProgress,
@ -409,6 +414,10 @@ export function deleteItem(
);
handleError(error, "GalleryUtils/deleteItem", `Failed to remove ${name} from gallery`);
} finally {
if (afterDelete) {
afterDelete();
}
}
NotificationConsoleUtils.clearInProgressMessageWithId(notificationId);