Public gallery improvements (#409)

- [x] Don't show extension in name field for publish
- [x] Open "Your published work" tab after publishing
- [x] Continue showing dialog for Report Abuse status
- [x] For showing COC in Public Gallery tab show backdrop of thumbnails
- [x] Liked -> My Favorites & Your published work -> My published work
This commit is contained in:
Tanuj Mittal 2021-01-29 22:34:38 +05:30 committed by GitHub
parent 59113d7bbf
commit 9278654479
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 190 additions and 66 deletions

View File

@ -3,7 +3,13 @@ import { Dialog, DialogType, DialogFooter, IDialogProps } from "office-ui-fabric
import { IButtonProps, PrimaryButton, DefaultButton } from "office-ui-fabric-react/lib/Button"; import { IButtonProps, PrimaryButton, DefaultButton } from "office-ui-fabric-react/lib/Button";
import { ITextFieldProps, TextField } from "office-ui-fabric-react/lib/TextField"; import { ITextFieldProps, TextField } from "office-ui-fabric-react/lib/TextField";
import { Link } from "office-ui-fabric-react/lib/Link"; import { Link } from "office-ui-fabric-react/lib/Link";
import { ChoiceGroup, FontIcon, IChoiceGroupProps } from "office-ui-fabric-react"; import {
ChoiceGroup,
FontIcon,
IChoiceGroupProps,
IProgressIndicatorProps,
ProgressIndicator,
} from "office-ui-fabric-react";
export interface TextFieldProps extends ITextFieldProps { export interface TextFieldProps extends ITextFieldProps {
label: string; label: string;
@ -27,6 +33,7 @@ export interface DialogProps {
choiceGroupProps?: IChoiceGroupProps; choiceGroupProps?: IChoiceGroupProps;
textFieldProps?: TextFieldProps; textFieldProps?: TextFieldProps;
linkProps?: LinkProps; linkProps?: LinkProps;
progressIndicatorProps?: IProgressIndicatorProps;
primaryButtonText: string; primaryButtonText: string;
secondaryButtonText: string; secondaryButtonText: string;
onPrimaryButtonClick: () => void; onPrimaryButtonClick: () => void;
@ -69,6 +76,7 @@ export class DialogComponent extends React.Component<DialogProps, {}> {
const choiceGroupProps: IChoiceGroupProps = this.props.choiceGroupProps; const choiceGroupProps: IChoiceGroupProps = this.props.choiceGroupProps;
const textFieldProps: ITextFieldProps = this.props.textFieldProps; const textFieldProps: ITextFieldProps = this.props.textFieldProps;
const linkProps: LinkProps = this.props.linkProps; const linkProps: LinkProps = this.props.linkProps;
const progressIndicatorProps: IProgressIndicatorProps = this.props.progressIndicatorProps;
const primaryButtonProps: IButtonProps = { const primaryButtonProps: IButtonProps = {
text: this.props.primaryButtonText, text: this.props.primaryButtonText,
disabled: this.props.primaryButtonDisabled || false, disabled: this.props.primaryButtonDisabled || false,
@ -91,6 +99,7 @@ export class DialogComponent extends React.Component<DialogProps, {}> {
{linkProps.linkText} <FontIcon iconName="NavigateExternalInline" /> {linkProps.linkText} <FontIcon iconName="NavigateExternalInline" />
</Link> </Link>
)} )}
{progressIndicatorProps && <ProgressIndicator {...progressIndicatorProps} />}
<DialogFooter> <DialogFooter>
<PrimaryButton {...primaryButtonProps} /> <PrimaryButton {...primaryButtonProps} />
{secondaryButtonProps && <DefaultButton {...secondaryButtonProps} />} {secondaryButtonProps && <DefaultButton {...secondaryButtonProps} />}

View File

@ -127,7 +127,7 @@ export class GalleryCardComponent extends React.Component<GalleryCardComponentPr
{this.props.isFavorite !== undefined && {this.props.isFavorite !== undefined &&
this.generateIconButtonWithTooltip( this.generateIconButtonWithTooltip(
this.props.isFavorite ? "HeartFill" : "Heart", this.props.isFavorite ? "HeartFill" : "Heart",
this.props.isFavorite ? "Unlike" : "Like", this.props.isFavorite ? "Unfavorite" : "Favorite",
"left", "left",
this.props.isFavorite ? this.props.onUnfavoriteClick : this.props.onFavoriteClick this.props.isFavorite ? this.props.onUnfavoriteClick : this.props.onFavoriteClick
)} )}

View File

@ -185,7 +185,7 @@ exports[`GalleryCardComponent renders 1`] = `
"gapSpace": 0, "gapSpace": 0,
} }
} }
content="Like" content="Favorite"
id="TooltipHost-IconButton-Heart" id="TooltipHost-IconButton-Heart"
styles={ styles={
Object { Object {
@ -197,14 +197,14 @@ exports[`GalleryCardComponent renders 1`] = `
} }
> >
<CustomizedIconButton <CustomizedIconButton
ariaLabel="Like" ariaLabel="Favorite"
iconProps={ iconProps={
Object { Object {
"iconName": "Heart", "iconName": "Heart",
} }
} }
onClick={[Function]} onClick={[Function]}
title="Like" title="Favorite"
/> />
</StyledTooltipHostBase> </StyledTooltipHostBase>
<StyledTooltipHostBase <StyledTooltipHostBase

View File

@ -7,14 +7,20 @@ import {
} from "./GalleryAndNotebookViewerComponent"; } from "./GalleryAndNotebookViewerComponent";
export class GalleryAndNotebookViewerComponentAdapter implements ReactAdapter { export class GalleryAndNotebookViewerComponentAdapter implements ReactAdapter {
private key: string;
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
constructor(private props: GalleryAndNotebookViewerComponentProps) { constructor(private props: GalleryAndNotebookViewerComponentProps) {
this.reset();
this.parameters = ko.observable<number>(Date.now()); this.parameters = ko.observable<number>(Date.now());
} }
public renderComponent(): JSX.Element { public renderComponent(): JSX.Element {
return <GalleryAndNotebookViewerComponent {...this.props} />; return <GalleryAndNotebookViewerComponent key={this.key} {...this.props} />;
}
public reset(): void {
this.key = `GalleryAndNotebookViewerComponent-${Date.now()}`;
} }
public triggerRender(): void { public triggerRender(): void {

View File

@ -7,3 +7,12 @@
width: 100%; width: 100%;
font-family: @DataExplorerFont; font-family: @DataExplorerFont;
} }
.publicGalleryTabContainer {
position: relative;
}
.publicGalleryTabOverlayContent {
background: white;
padding: 20px;
}

View File

@ -10,6 +10,7 @@ import {
IRectangle, IRectangle,
Label, Label,
List, List,
Overlay,
Pivot, Pivot,
PivotItem, PivotItem,
SearchBox, SearchBox,
@ -74,14 +75,14 @@ interface GalleryTabInfo {
export class GalleryViewerComponent extends React.Component<GalleryViewerComponentProps, GalleryViewerComponentState> { export class GalleryViewerComponent extends React.Component<GalleryViewerComponentProps, GalleryViewerComponentState> {
public static readonly OfficialSamplesTitle = "Official samples"; public static readonly OfficialSamplesTitle = "Official samples";
public static readonly PublicGalleryTitle = "Public gallery"; public static readonly PublicGalleryTitle = "Public gallery";
public static readonly FavoritesTitle = "Liked"; public static readonly FavoritesTitle = "My favorites";
public static readonly PublishedTitle = "Your published work"; public static readonly PublishedTitle = "My published work";
private static readonly rowsPerPage = 5; private static readonly rowsPerPage = 5;
private static readonly mostViewedText = "Most viewed"; private static readonly mostViewedText = "Most viewed";
private static readonly mostDownloadedText = "Most downloaded"; private static readonly mostDownloadedText = "Most downloaded";
private static readonly mostFavoritedText = "Most liked"; private static readonly mostFavoritedText = "Most favorited";
private static readonly mostRecentText = "Most recent"; private static readonly mostRecentText = "Most recent";
private readonly sortingOptions: IDropdownOption[]; private readonly sortingOptions: IDropdownOption[];
@ -222,8 +223,8 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
content: this.isEmptyData(data) content: this.isEmptyData(data)
? this.createEmptyTabContent( ? this.createEmptyTabContent(
"ContactHeart", "ContactHeart",
"You have not liked anything", "You have not favorited anything",
"Like any notebook from Official Samples or Public gallery" "Favorite any notebook from Official samples or Public gallery"
) )
: this.createSearchBarHeader(this.createCardsTabContent(data)), : this.createSearchBarHeader(this.createCardsTabContent(data)),
}; };
@ -245,7 +246,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
private createPublishedNotebooksTabContent = (data: IGalleryItem[]): JSX.Element => { private createPublishedNotebooksTabContent = (data: IGalleryItem[]): JSX.Element => {
const { published, underReview, removed } = GalleryUtils.filterPublishedNotebooks(data); const { published, underReview, removed } = GalleryUtils.filterPublishedNotebooks(data);
const content = ( const content = (
<Stack tokens={{ childrenGap: 10 }}> <Stack tokens={{ childrenGap: 20 }}>
{published?.length > 0 && {published?.length > 0 &&
this.createPublishedNotebooksSectionContent( this.createPublishedNotebooksSectionContent(
undefined, undefined,
@ -276,7 +277,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
content: JSX.Element content: JSX.Element
): JSX.Element => { ): JSX.Element => {
return ( return (
<Stack tokens={{ childrenGap: 5 }}> <Stack tokens={{ childrenGap: 10 }}>
{title && <Text styles={{ root: { fontWeight: FontWeights.semibold } }}>{title}</Text>} {title && <Text styles={{ root: { fontWeight: FontWeights.semibold } }}>{title}</Text>}
{description && <Text>{description}</Text>} {description && <Text>{description}</Text>}
{content} {content}
@ -285,15 +286,22 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
}; };
private createPublicGalleryTabContent(data: IGalleryItem[], acceptedCodeOfConduct: boolean): JSX.Element { private createPublicGalleryTabContent(data: IGalleryItem[], acceptedCodeOfConduct: boolean): JSX.Element {
return acceptedCodeOfConduct === false ? ( return (
<CodeOfConductComponent <div className="publicGalleryTabContainer">
junoClient={this.props.junoClient} {this.createSearchBarHeader(this.createCardsTabContent(data))}
onAcceptCodeOfConduct={(result: boolean) => { {acceptedCodeOfConduct === false && (
this.setState({ isCodeOfConductAccepted: result }); <Overlay isDarkThemed>
}} <div className="publicGalleryTabOverlayContent">
/> <CodeOfConductComponent
) : ( junoClient={this.props.junoClient}
this.createSearchBarHeader(this.createCardsTabContent(data)) onAcceptCodeOfConduct={(result: boolean) => {
this.setState({ isCodeOfConductAccepted: result });
}}
/>
</div>
</Overlay>
)}
</div>
); );
} }

View File

@ -3,14 +3,11 @@
*/ */
import { Notebook } from "@nteract/commutable"; import { Notebook } from "@nteract/commutable";
import { createContentRef } from "@nteract/core"; import { createContentRef } from "@nteract/core";
import { IChoiceGroupProps, Icon, Link, ProgressIndicator } from "office-ui-fabric-react"; import { IChoiceGroupProps, Icon, IProgressIndicatorProps, Link, ProgressIndicator } from "office-ui-fabric-react";
import * as React from "react"; import * as React from "react";
import { contents } from "rx-jupyter"; import { contents } from "rx-jupyter";
import * as Logger from "../../../Common/Logger";
import { IGalleryItem, JunoClient } from "../../../Juno/JunoClient"; import { IGalleryItem, JunoClient } from "../../../Juno/JunoClient";
import * as GalleryUtils from "../../../Utils/GalleryUtils"; import * as GalleryUtils from "../../../Utils/GalleryUtils";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
import { NotebookClientV2 } from "../../Notebook/NotebookClientV2"; import { NotebookClientV2 } from "../../Notebook/NotebookClientV2";
import { NotebookComponentBootstrapper } from "../../Notebook/NotebookComponent/NotebookComponentBootstrapper"; import { NotebookComponentBootstrapper } from "../../Notebook/NotebookComponent/NotebookComponentBootstrapper";
import NotebookReadOnlyRenderer from "../../Notebook/NotebookRenderer/NotebookReadOnlyRenderer"; import NotebookReadOnlyRenderer from "../../Notebook/NotebookRenderer/NotebookReadOnlyRenderer";
@ -21,7 +18,7 @@ import Explorer from "../../Explorer";
import { NotebookV4 } from "@nteract/commutable/lib/v4"; import { NotebookV4 } from "@nteract/commutable/lib/v4";
import { SessionStorageUtility } from "../../../Shared/StorageUtility"; import { SessionStorageUtility } from "../../../Shared/StorageUtility";
import { DialogHost } from "../../../Utils/GalleryUtils"; import { DialogHost } from "../../../Utils/GalleryUtils";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils"; import { handleError } from "../../../Common/ErrorHandlingUtils";
export interface NotebookViewerComponentProps { export interface NotebookViewerComponentProps {
container?: Explorer; container?: Explorer;
@ -178,6 +175,32 @@ export class NotebookViewerComponent
}; };
} }
// DialogHost
showOkModalDialog(
title: string,
msg: string,
okLabel: string,
onOk: () => void,
progressIndicatorProps?: IProgressIndicatorProps
): void {
this.setState({
dialogProps: {
isModal: true,
visible: true,
title,
subText: msg,
primaryButtonText: okLabel,
onPrimaryButtonClick: () => {
this.setState({ dialogProps: undefined });
onOk && onOk();
},
secondaryButtonText: undefined,
onSecondaryButtonClick: undefined,
progressIndicatorProps,
},
});
}
// DialogHost // DialogHost
showOkCancelModalDialog( showOkCancelModalDialog(
title: string, title: string,
@ -186,8 +209,10 @@ export class NotebookViewerComponent
onOk: () => void, onOk: () => void,
cancelLabel: string, cancelLabel: string,
onCancel: () => void, onCancel: () => void,
progressIndicatorProps?: IProgressIndicatorProps,
choiceGroupProps?: IChoiceGroupProps, choiceGroupProps?: IChoiceGroupProps,
textFieldProps?: TextFieldProps textFieldProps?: TextFieldProps,
primaryButtonDisabled?: boolean
): void { ): void {
this.setState({ this.setState({
dialogProps: { dialogProps: {
@ -205,8 +230,10 @@ export class NotebookViewerComponent
this.setState({ dialogProps: undefined }); this.setState({ dialogProps: undefined });
onCancel && onCancel(); onCancel && onCancel();
}, },
progressIndicatorProps,
choiceGroupProps, choiceGroupProps,
textFieldProps, textFieldProps,
primaryButtonDisabled,
}, },
}); });
} }

View File

@ -91,6 +91,7 @@ import { appInsights } from "../Shared/appInsights";
import { SelfServeLoadingComponentAdapter } from "../SelfServe/SelfServeLoadingComponentAdapter"; import { SelfServeLoadingComponentAdapter } from "../SelfServe/SelfServeLoadingComponentAdapter";
import { SelfServeType } from "../SelfServe/SelfServeUtils"; import { SelfServeType } from "../SelfServe/SelfServeUtils";
import { SelfServeComponentAdapter } from "../SelfServe/SelfServeComponentAdapter"; import { SelfServeComponentAdapter } from "../SelfServe/SelfServeComponentAdapter";
import { GalleryTab } from "./Controls/NotebookGallery/GalleryViewerComponent";
BindingHandlersRegisterer.registerBindingHandlers(); BindingHandlersRegisterer.registerBindingHandlers();
// Hold a reference to ComponentRegisterer to prevent transpiler to ignore import // Hold a reference to ComponentRegisterer to prevent transpiler to ignore import
@ -2810,10 +2811,36 @@ export default class Explorer {
} }
} }
public async openGallery(notebookUrl?: string, galleryItem?: IGalleryItem, isFavorite?: boolean) { public async openGallery(
selectedTab?: GalleryTab,
notebookUrl?: string,
galleryItem?: IGalleryItem,
isFavorite?: boolean
) {
let title: string = "Gallery"; let title: string = "Gallery";
let hashLocation: string = "gallery"; let hashLocation: string = "gallery";
const galleryTabOptions: any = {
// GalleryTabOptions
account: userContext.databaseAccount,
container: this,
junoClient: this.notebookManager?.junoClient,
selectedTab: selectedTab || GalleryTab.OfficialSamples,
notebookUrl,
galleryItem,
isFavorite,
// TabOptions
tabKind: ViewModels.CollectionTabKind.Gallery,
title: title,
tabPath: title,
documentClientUtility: null,
isActive: ko.observable(false),
hashLocation: hashLocation,
onUpdateTabsButtons: this.onUpdateTabsButtons,
isTabsContentExpanded: ko.observable(true),
onLoadStartKey: null,
};
const galleryTabs = this.tabsManager.getTabs( const galleryTabs = this.tabsManager.getTabs(
ViewModels.CollectionTabKind.Gallery, ViewModels.CollectionTabKind.Gallery,
(tab) => tab.hashLocation() == hashLocation (tab) => tab.hashLocation() == hashLocation
@ -2822,31 +2849,12 @@ export default class Explorer {
if (galleryTab) { if (galleryTab) {
this.tabsManager.activateTab(galleryTab); this.tabsManager.activateTab(galleryTab);
(galleryTab as any).reset(galleryTabOptions);
} else { } else {
if (!this.galleryTab) { if (!this.galleryTab) {
this.galleryTab = await import(/* webpackChunkName: "GalleryTab" */ "./Tabs/GalleryTab"); this.galleryTab = await import(/* webpackChunkName: "GalleryTab" */ "./Tabs/GalleryTab");
} }
const newTab = new this.galleryTab.default(galleryTabOptions);
const newTab = new this.galleryTab.default({
// GalleryTabOptions
account: userContext.databaseAccount,
container: this,
junoClient: this.notebookManager?.junoClient,
notebookUrl,
galleryItem,
isFavorite,
// TabOptions
tabKind: ViewModels.CollectionTabKind.Gallery,
title: title,
tabPath: title,
documentClientUtility: null,
isActive: ko.observable(false),
hashLocation: hashLocation,
onUpdateTabsButtons: this.onUpdateTabsButtons,
isTabsContentExpanded: ko.observable(true),
onLoadStartKey: null,
});
this.tabsManager.activateNewTab(newTab); this.tabsManager.activateNewTab(newTab);
} }
} }

View File

@ -11,6 +11,7 @@ import { toJS } from "@nteract/commutable";
import { CodeOfConductComponent } from "../Controls/NotebookGallery/CodeOfConductComponent"; import { CodeOfConductComponent } from "../Controls/NotebookGallery/CodeOfConductComponent";
import { HttpStatusCodes } from "../../Common/Constants"; import { HttpStatusCodes } from "../../Common/Constants";
import { handleError, getErrorMessage } from "../../Common/ErrorHandlingUtils"; import { handleError, getErrorMessage } from "../../Common/ErrorHandlingUtils";
import { GalleryTab } from "../Controls/NotebookGallery/GalleryViewerComponent";
export class PublishNotebookPaneAdapter implements ReactAdapter { export class PublishNotebookPaneAdapter implements ReactAdapter {
parameters: ko.Observable<number>; parameters: ko.Observable<number>;
@ -163,6 +164,7 @@ export class PublishNotebookPaneAdapter implements ReactAdapter {
); );
} else { } else {
NotificationConsoleUtils.logConsoleInfo(`Published ${this.name} to gallery`); NotificationConsoleUtils.logConsoleInfo(`Published ${this.name} to gallery`);
this.container.openGallery(GalleryTab.Published);
} }
} }
} catch (error) { } catch (error) {

View File

@ -172,11 +172,12 @@ export class PublishNotebookPaneComponent extends React.Component<PublishNoteboo
this.nameProps = { this.nameProps = {
label: "Name", label: "Name",
ariaLabel: "Name", ariaLabel: "Name",
defaultValue: this.props.notebookName, defaultValue: FileSystemUtil.stripExtension(this.props.notebookName, "ipynb"),
required: true, required: true,
onChange: (event, newValue) => { onChange: (event, newValue) => {
this.props.onChangeName(newValue); const notebookName = newValue + ".ipynb";
this.setState({ notebookName: newValue }); this.props.onChangeName(notebookName);
this.setState({ notebookName });
}, },
}; };

View File

@ -25,7 +25,7 @@ exports[`PublishNotebookPaneComponent renders 1`] = `
<StackItem> <StackItem>
<StyledTextFieldBase <StyledTextFieldBase
ariaLabel="Name" ariaLabel="Name"
defaultValue="SampleNotebook.ipynb" defaultValue="SampleNotebook"
label="Name" label="Name"
onChange={[Function]} onChange={[Function]}
required={true} required={true}

View File

@ -11,6 +11,7 @@ interface GalleryTabOptions extends ViewModels.TabOptions {
account: DatabaseAccount; account: DatabaseAccount;
container: Explorer; container: Explorer;
junoClient: JunoClient; junoClient: JunoClient;
selectedTab: GalleryViewerTab;
notebookUrl?: string; notebookUrl?: string;
galleryItem?: IGalleryItem; galleryItem?: IGalleryItem;
isFavorite?: boolean; isFavorite?: boolean;
@ -21,24 +22,42 @@ interface GalleryTabOptions extends ViewModels.TabOptions {
*/ */
export default class GalleryTab extends TabsBase { export default class GalleryTab extends TabsBase {
private container: Explorer; private container: Explorer;
private galleryAndNotebookViewerComponentProps: GalleryAndNotebookViewerComponentProps;
public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter; public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter;
constructor(options: GalleryTabOptions) { constructor(options: GalleryTabOptions) {
super(options); super(options);
this.container = options.container; this.container = options.container;
const props: GalleryAndNotebookViewerComponentProps = {
this.galleryAndNotebookViewerComponentProps = {
container: options.container, container: options.container,
junoClient: options.junoClient, junoClient: options.junoClient,
notebookUrl: options.notebookUrl, notebookUrl: options.notebookUrl,
galleryItem: options.galleryItem, galleryItem: options.galleryItem,
isFavorite: options.isFavorite, isFavorite: options.isFavorite,
selectedTab: GalleryViewerTab.OfficialSamples, selectedTab: options.selectedTab,
sortBy: SortBy.MostViewed, sortBy: SortBy.MostViewed,
searchText: undefined, searchText: undefined,
}; };
this.galleryAndNotebookViewerComponentAdapter = new GalleryAndNotebookViewerComponentAdapter(
this.galleryAndNotebookViewerComponentProps
);
}
this.galleryAndNotebookViewerComponentAdapter = new GalleryAndNotebookViewerComponentAdapter(props); public reset(options: GalleryTabOptions) {
this.container = options.container;
this.galleryAndNotebookViewerComponentProps.container = options.container;
this.galleryAndNotebookViewerComponentProps.junoClient = options.junoClient;
this.galleryAndNotebookViewerComponentProps.notebookUrl = options.notebookUrl;
this.galleryAndNotebookViewerComponentProps.galleryItem = options.galleryItem;
this.galleryAndNotebookViewerComponentProps.isFavorite = options.isFavorite;
this.galleryAndNotebookViewerComponentProps.selectedTab = options.selectedTab;
this.galleryAndNotebookViewerComponentProps.sortBy = SortBy.MostViewed;
this.galleryAndNotebookViewerComponentProps.searchText = undefined;
this.galleryAndNotebookViewerComponentAdapter.reset();
this.galleryAndNotebookViewerComponentAdapter.triggerRender();
} }
protected getContainer(): Explorer { protected getContainer(): Explorer {

View File

@ -7,7 +7,7 @@ import {
GalleryViewerComponent, GalleryViewerComponent,
} from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent"; } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent";
import Explorer from "../Explorer/Explorer"; import Explorer from "../Explorer/Explorer";
import { IChoiceGroupOption, IChoiceGroupProps } from "office-ui-fabric-react"; import { IChoiceGroupOption, IChoiceGroupProps, IProgressIndicatorProps } from "office-ui-fabric-react";
import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent"; import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent";
import { handleError } from "../Common/ErrorHandlingUtils"; import { handleError } from "../Common/ErrorHandlingUtils";
import { HttpStatusCodes } from "../Common/Constants"; import { HttpStatusCodes } from "../Common/Constants";
@ -81,6 +81,14 @@ export interface GalleryViewerProps {
} }
export interface DialogHost { export interface DialogHost {
showOkModalDialog(
title: string,
msg: string,
okLabel: string,
onOk: () => void,
progressIndicatorProps?: IProgressIndicatorProps
): void;
showOkCancelModalDialog( showOkCancelModalDialog(
title: string, title: string,
msg: string, msg: string,
@ -88,8 +96,10 @@ export interface DialogHost {
onOk: () => void, onOk: () => void,
cancelLabel: string, cancelLabel: string,
onCancel: () => void, onCancel: () => void,
progressIndicatorProps?: IProgressIndicatorProps,
choiceGroupProps?: IChoiceGroupProps, choiceGroupProps?: IChoiceGroupProps,
textFieldProps?: TextFieldProps textFieldProps?: TextFieldProps,
primaryButtonDisabled?: boolean
): void; ): void;
} }
@ -108,8 +118,17 @@ export function reportAbuse(
undefined, undefined,
"Report Abuse", "Report Abuse",
async () => { async () => {
const clearSubmitReportNotification = NotificationConsoleUtils.logConsoleProgress( dialogHost.showOkCancelModalDialog(
`Submitting your report on ${data.name} violating code of conduct` "Report Abuse",
`Submitting your report on ${data.name} violating code of conduct`,
"Reporting...",
undefined,
"Cancel",
undefined,
{},
undefined,
undefined,
true
); );
try { try {
@ -118,9 +137,16 @@ export function reportAbuse(
throw new Error(`Received HTTP ${response.status} when submitting report for ${data.name}`); throw new Error(`Received HTTP ${response.status} when submitting report for ${data.name}`);
} }
NotificationConsoleUtils.logConsoleInfo( dialogHost.showOkModalDialog(
`Your report on ${data.name} has been submitted. Thank you for reporting the violation.` "Report Abuse",
`Your report on ${data.name} has been submitted. Thank you for reporting the violation.`,
"OK",
undefined,
{
percentComplete: 1,
}
); );
onComplete(response.data); onComplete(response.data);
} catch (error) { } catch (error) {
handleError( handleError(
@ -128,12 +154,21 @@ export function reportAbuse(
"GalleryUtils/reportAbuse", "GalleryUtils/reportAbuse",
`Failed to submit report on ${data.name} violating code of conduct` `Failed to submit report on ${data.name} violating code of conduct`
); );
}
clearSubmitReportNotification(); dialogHost.showOkModalDialog(
"Report Abuse",
`Failed to submit report on ${data.name} violating code of conduct`,
"OK",
undefined,
{
percentComplete: 1,
}
);
}
}, },
"Cancel", "Cancel",
undefined, undefined,
undefined,
{ {
label: "How does this content violate the code of conduct?", label: "How does this content violate the code of conduct?",
options: abuseCategories, options: abuseCategories,