Migrate UploadItemPane to react (#17)
* Create GenericPaneComponent and use it to migrate UploadItemsPane to React * Add helper functions for building each panel section * Address comments and some styling changes * Unsubscribe to isNotificationConsoleExpanded when component unmounts
This commit is contained in:
parent
aa8236666e
commit
582ac865ff
|
@ -570,6 +570,12 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.fileImportButton {
|
||||
height: 24px;
|
||||
border: @ButtonBorderWidth solid transparent;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.fileUploadSummaryContainer {
|
||||
margin-top: 40px;
|
||||
|
||||
|
@ -1016,6 +1022,18 @@ menuQuickStart {
|
|||
background: #262626;
|
||||
}
|
||||
|
||||
.panelContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.panelContentWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.contextual-pane {
|
||||
top: 0px;
|
||||
right: 0 !important;
|
||||
|
@ -1232,23 +1250,25 @@ menuQuickStart {
|
|||
padding: 2px 30px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
|
||||
&:active {
|
||||
border-color: #0072c6;
|
||||
background-color: #0072c6;
|
||||
}
|
||||
}
|
||||
|
||||
.btncreatecoll1:hover {
|
||||
background: @AccentMediumHigh;
|
||||
.leftpanel-okbut .genericPaneSubmitBtn {
|
||||
border: 1px solid @AccentMediumHigh;
|
||||
background-color: @AccentMediumHigh;
|
||||
color: #fff;
|
||||
border-color: @AccentMediumHigh;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
}
|
||||
height: 24px;
|
||||
|
||||
.btncreatecoll1:active {
|
||||
border: 1px solid #0072c6;
|
||||
background-color: #0072c6;
|
||||
color: white;
|
||||
padding: 2px 30px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
&:active {
|
||||
border-color: #0072c6;
|
||||
background-color: #0072c6;
|
||||
}
|
||||
}
|
||||
|
||||
.btncreatecoll1-off {
|
||||
|
@ -1361,6 +1381,15 @@ p {
|
|||
color: #000;
|
||||
}
|
||||
|
||||
.headerline .closePaneBtn {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
margin-right: 4px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.closeImg {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
|
@ -1710,6 +1739,13 @@ input::-webkit-calendar-picker-indicator {
|
|||
margin: (2 * @MediumSpace) 0px;
|
||||
}
|
||||
|
||||
.contextual-pane .panelMainContent {
|
||||
padding-left: 34px;
|
||||
padding-right: 34px;
|
||||
color: @BaseDark;
|
||||
margin: (2 * @MediumSpace) 0px;
|
||||
}
|
||||
|
||||
.contextual-pane .paneFooter {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
|
|
|
@ -127,6 +127,7 @@ export class Features {
|
|||
public static readonly enableFixedCollectionWithSharedThroughput = "enablefixedcollectionwithsharedthroughput";
|
||||
public static readonly enableAutoPilotV2 = "enableautopilotv2";
|
||||
public static readonly ttl90Days = "ttl90days";
|
||||
public static readonly enableRightPanelV2 = "enablerightpanelv2";
|
||||
}
|
||||
|
||||
export class AfecFeatures {
|
||||
|
|
|
@ -27,6 +27,7 @@ import { Splitter } from "../Common/Splitter";
|
|||
import { StringInputPane } from "../Explorer/Panes/StringInputPane";
|
||||
import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent";
|
||||
import { UploadDetails } from "../workers/upload/definitions";
|
||||
import { UploadItemsPaneAdapter } from "../Explorer/Panes/UploadItemsPaneAdapter";
|
||||
|
||||
export interface ExplorerOptions {
|
||||
documentClientUtility: DocumentClientUtilityBase;
|
||||
|
@ -87,6 +88,7 @@ export interface Explorer {
|
|||
isGalleryEnabled: ko.Computed<boolean>;
|
||||
isGitHubPaneEnabled: ko.Observable<boolean>;
|
||||
isGraphsEnabled: ko.Computed<boolean>;
|
||||
isRightPanelV2Enabled: ko.Computed<boolean>;
|
||||
canExceedMaximumValue: ko.Computed<boolean>;
|
||||
hasAutoPilotV2FeatureFlag: ko.Computed<boolean>;
|
||||
isHostedDataExplorerEnabled: ko.Computed<boolean>;
|
||||
|
@ -141,6 +143,7 @@ export interface Explorer {
|
|||
executeSprocParamsPane: ExecuteSprocParamsPane;
|
||||
renewAdHocAccessPane: RenewAdHocAccessPane;
|
||||
uploadItemsPane: UploadItemsPane;
|
||||
uploadItemsPaneAdapter: UploadItemsPaneAdapter;
|
||||
loadQueryPane: LoadQueryPane;
|
||||
saveQueryPane: ContextualPane;
|
||||
browseQueriesPane: BrowseQueriesPane;
|
||||
|
|
|
@ -86,6 +86,7 @@ import { StringInputPane } from "./Panes/StringInputPane";
|
|||
import { TableColumnOptionsPane } from "./Panes/Tables/TableColumnOptionsPane";
|
||||
import { UploadFilePane } from "./Panes/UploadFilePane";
|
||||
import { UploadItemsPane } from "./Panes/UploadItemsPane";
|
||||
import { UploadItemsPaneAdapter } from "./Panes/UploadItemsPaneAdapter";
|
||||
|
||||
BindingHandlersRegisterer.registerBindingHandlers();
|
||||
// Hold a reference to ComponentRegisterer to prevent transpiler to ignore import
|
||||
|
@ -188,6 +189,7 @@ export default class Explorer implements ViewModels.Explorer {
|
|||
public executeSprocParamsPane: ViewModels.ExecuteSprocParamsPane;
|
||||
public renewAdHocAccessPane: ViewModels.RenewAdHocAccessPane;
|
||||
public uploadItemsPane: ViewModels.UploadItemsPane;
|
||||
public uploadItemsPaneAdapter: UploadItemsPaneAdapter;
|
||||
public loadQueryPane: ViewModels.LoadQueryPane;
|
||||
public saveQueryPane: ViewModels.ContextualPane;
|
||||
public browseQueriesPane: ViewModels.BrowseQueriesPane;
|
||||
|
@ -205,6 +207,7 @@ export default class Explorer implements ViewModels.Explorer {
|
|||
public isGitHubPaneEnabled: ko.Observable<boolean>;
|
||||
public isGraphsEnabled: ko.Computed<boolean>;
|
||||
public isHostedDataExplorerEnabled: ko.Computed<boolean>;
|
||||
public isRightPanelV2Enabled: ko.Computed<boolean>;
|
||||
public canExceedMaximumValue: ko.Computed<boolean>;
|
||||
public hasAutoPilotV2FeatureFlag: ko.Computed<boolean>;
|
||||
|
||||
|
@ -551,6 +554,7 @@ export default class Explorer implements ViewModels.Explorer {
|
|||
!this.isRunningOnNationalCloud() &&
|
||||
!this.isPreferredApiGraph()
|
||||
);
|
||||
this.isRightPanelV2Enabled = ko.computed<boolean>(() => this.isFeatureEnabled(Constants.Features.enableRightPanelV2));
|
||||
this.defaultExperience.subscribe((defaultExperience: string) => {
|
||||
if (
|
||||
defaultExperience &&
|
||||
|
@ -707,6 +711,8 @@ export default class Explorer implements ViewModels.Explorer {
|
|||
container: this
|
||||
});
|
||||
|
||||
this.uploadItemsPaneAdapter = new UploadItemsPaneAdapter(this);
|
||||
|
||||
this.loadQueryPane = new LoadQueryPane({
|
||||
documentClientUtility: this.documentClientUtility,
|
||||
id: "loadquerypane",
|
||||
|
|
|
@ -19,6 +19,7 @@ import { TableColumnOptionsPane } from "../../src/Explorer/Panes/Tables/TableCol
|
|||
import { TextFieldProps } from "./Controls/DialogReactComponent/DialogComponent";
|
||||
import { UploadDetails } from "../workers/upload/definitions";
|
||||
import { UploadFilePane } from "./Panes/UploadFilePane";
|
||||
import { UploadItemsPaneAdapter } from "./Panes/UploadItemsPaneAdapter";
|
||||
import { Versions } from "../../src/Contracts/ExplorerContracts";
|
||||
import { CollectionCreationDefaults } from "../Shared/Constants";
|
||||
|
||||
|
@ -86,6 +87,7 @@ export class ExplorerStub implements ViewModels.Explorer {
|
|||
public settingsPane: ViewModels.SettingsPane;
|
||||
public executeSprocParamsPane: ViewModels.ExecuteSprocParamsPane;
|
||||
public uploadItemsPane: ViewModels.UploadItemsPane;
|
||||
public uploadItemsPaneAdapter: UploadItemsPaneAdapter;
|
||||
public loadQueryPane: ViewModels.LoadQueryPane;
|
||||
public saveQueryPane: ViewModels.ContextualPane;
|
||||
public browseQueriesPane: ViewModels.BrowseQueriesPane;
|
||||
|
@ -97,6 +99,7 @@ export class ExplorerStub implements ViewModels.Explorer {
|
|||
public isGalleryEnabled: ko.Computed<boolean>;
|
||||
public isGitHubPaneEnabled: ko.Observable<boolean>;
|
||||
public isGraphsEnabled: ko.Computed<boolean>;
|
||||
public isRightPanelV2Enabled: ko.Computed<boolean>;
|
||||
public canExceedMaximumValue: ko.Computed<boolean>;
|
||||
public isHostedDataExplorerEnabled: ko.Computed<boolean>;
|
||||
public parentFrameDataExplorerVersion: ko.Observable<string> = ko.observable<string>(Versions.DataExplorer);
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
import * as React from "react";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
|
||||
import { KeyCodes } from "../../Common/Constants";
|
||||
import { Subscription } from "knockout";
|
||||
import ErrorRedIcon from "../../../images/error_red.svg";
|
||||
import LoadingIndicatorIcon from "../../../images/LoadingIndicator_3Squares.gif";
|
||||
|
||||
export interface GenericRightPaneProps {
|
||||
container: ViewModels.Explorer;
|
||||
content: JSX.Element;
|
||||
formError: string;
|
||||
formErrorDetail: string;
|
||||
id: string;
|
||||
isExecuting: boolean;
|
||||
onClose: () => void;
|
||||
onSubmit: () => void;
|
||||
submitButtonText: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface GenericRightPaneState {
|
||||
panelHeight: number;
|
||||
}
|
||||
|
||||
export class GenericRightPaneComponent extends React.Component<GenericRightPaneProps, GenericRightPaneState> {
|
||||
private notificationConsoleSubscription: Subscription;
|
||||
|
||||
constructor(props: GenericRightPaneProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
panelHeight: this.getPanelHeight()
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
this.notificationConsoleSubscription = this.props.container.isNotificationConsoleExpanded.subscribe(() => {
|
||||
this.setState({ panelHeight: this.getPanelHeight() });
|
||||
});
|
||||
this.props.container.isNotificationConsoleExpanded.extend({ rateLimit: 10 });
|
||||
}
|
||||
|
||||
public componentWillUnmount(): void {
|
||||
this.notificationConsoleSubscription && this.notificationConsoleSubscription.dispose();
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<div tabIndex={-1} onKeyDown={this.onKeyDown}>
|
||||
<div className="contextual-pane-out" onClick={this.props.onClose}></div>
|
||||
<div className="contextual-pane" id={this.props.id} style={{ height: this.state.panelHeight }} onKeyDown={this.onKeyDown}>
|
||||
<div className="panelContentWrapper">
|
||||
{this.createPanelHeader()}
|
||||
{this.createErrorSection()}
|
||||
{this.props.content}
|
||||
{this.createPanelFooter()}
|
||||
</div>
|
||||
{this.createLoadingScreen()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private createPanelHeader = (): JSX.Element => {
|
||||
return (
|
||||
<div className="firstdivbg headerline">
|
||||
<span id="databaseTitle">{this.props.title}</span>
|
||||
<IconButton
|
||||
ariaLabel="Close pane"
|
||||
title="Close pane"
|
||||
onClick={this.props.onClose}
|
||||
tabIndex={0}
|
||||
className="closePaneBtn"
|
||||
iconProps={{ iconName: "Cancel" }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private createErrorSection = (): JSX.Element => {
|
||||
return (
|
||||
<div className="warningErrorContainer" aria-live="assertive" hidden={!this.props.formError}>
|
||||
<div className="warningErrorContent">
|
||||
<span>
|
||||
<img className="paneErrorIcon" src={ErrorRedIcon} alt="Error" />
|
||||
</span>
|
||||
<span className="warningErrorDetailsLinkContainer">
|
||||
<span className="formErrors" title={this.props.formError}>
|
||||
{this.props.formError}
|
||||
</span>
|
||||
<a className="errorLink" role="link" hidden={!this.props.formErrorDetail} onClick={this.showErrorDetail}>
|
||||
More details
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private createPanelFooter = (): JSX.Element => {
|
||||
return (
|
||||
<div className="paneFooter">
|
||||
<div className="leftpanel-okbut">
|
||||
<PrimaryButton
|
||||
ariaLabel="Submit"
|
||||
title="Submit"
|
||||
onClick={this.props.onSubmit}
|
||||
tabIndex={0}
|
||||
className="genericPaneSubmitBtn"
|
||||
text={this.props.submitButtonText}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private createLoadingScreen = (): JSX.Element => {
|
||||
return (
|
||||
<div className="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" hidden={!this.props.isExecuting}>
|
||||
<img className="dataExplorerLoader" src={LoadingIndicatorIcon} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
|
||||
if (event.keyCode === KeyCodes.Escape) {
|
||||
this.props.onClose();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
private showErrorDetail = (): void => {
|
||||
this.props.container.expandConsole();
|
||||
};
|
||||
|
||||
private getPanelHeight = (): number => {
|
||||
const notificationConsoleElement: HTMLElement = document.getElementById("explorerNotificationConsole");
|
||||
return window.innerHeight - $(notificationConsoleElement).height();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
import * as Constants from "../../Common/Constants";
|
||||
import * as ErrorParserUtility from "../../Common/ErrorParserUtility";
|
||||
import * as ko from "knockout";
|
||||
import * as React from "react";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { IconButton } from "office-ui-fabric-react/lib/Button";
|
||||
import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||
import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions";
|
||||
import InfoBubbleIcon from "../../../images/info-bubble.svg";
|
||||
|
||||
const UPLOAD_FILE_SIZE_LIMIT = 2097152;
|
||||
|
||||
export class UploadItemsPaneAdapter implements ReactAdapter {
|
||||
public parameters: ko.Observable<number>;
|
||||
private isOpened: boolean;
|
||||
private isExecuting: boolean;
|
||||
private formError: string;
|
||||
private formErrorDetail: string;
|
||||
private selectedFiles: FileList;
|
||||
private selectedFilesTitle: string;
|
||||
private uploadFileData: UploadDetailsRecord[];
|
||||
|
||||
public constructor(private container: ViewModels.Explorer) {
|
||||
this.parameters = ko.observable(Date.now());
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public renderComponent(): JSX.Element {
|
||||
if (!this.isOpened) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const props: GenericRightPaneProps = {
|
||||
container: this.container,
|
||||
content: this.createContent(),
|
||||
formError: this.formError,
|
||||
formErrorDetail: this.formErrorDetail,
|
||||
id: "uploaditemspane",
|
||||
isExecuting: this.isExecuting,
|
||||
title: "Upload Items",
|
||||
submitButtonText: "Upload",
|
||||
onClose: () => this.close(),
|
||||
onSubmit: () => this.submit()
|
||||
};
|
||||
return <GenericRightPaneComponent {...props} />;
|
||||
}
|
||||
|
||||
public triggerRender(): void {
|
||||
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||
}
|
||||
|
||||
public open(): void {
|
||||
this.isOpened = true;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public submit(): void {
|
||||
this.formError = "";
|
||||
if (!this.selectedFiles || this.selectedFiles.length === 0) {
|
||||
this.formError = "No files specified";
|
||||
this.formErrorDetail = "No files were specified. Please input at least one file.";
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
"Could not upload items -- No files were specified. Please input at least one file."
|
||||
);
|
||||
this.triggerRender();
|
||||
return;
|
||||
} else if (this._totalFileSizeForFileList() > UPLOAD_FILE_SIZE_LIMIT) {
|
||||
this.formError = "Upload file size limit exceeded";
|
||||
this.formErrorDetail = "Total file upload size exceeds the 2 MB file size limit.";
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
"Could not upload items -- Total file upload size exceeds the 2 MB file size limit."
|
||||
);
|
||||
this.triggerRender();
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedCollection: ViewModels.Collection = this.container.findSelectedCollection();
|
||||
this.isExecuting = true;
|
||||
this.triggerRender();
|
||||
selectedCollection &&
|
||||
selectedCollection
|
||||
.uploadFiles(this.selectedFiles)
|
||||
.then(
|
||||
(uploadDetails: UploadDetails) => {
|
||||
this.uploadFileData = uploadDetails.data;
|
||||
this.selectedFiles = undefined;
|
||||
this.selectedFilesTitle = "";
|
||||
},
|
||||
error => {
|
||||
const message = ErrorParserUtility.parse(error);
|
||||
this.formError = message[0].message;
|
||||
this.formErrorDetail = message[0].message;
|
||||
}
|
||||
)
|
||||
.finally(() => {
|
||||
this.triggerRender();
|
||||
this.isExecuting = false;
|
||||
});
|
||||
}
|
||||
|
||||
private createContent = (): JSX.Element => {
|
||||
return (
|
||||
<div className="panelContent">
|
||||
{this.createMainContentSection()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private createMainContentSection = (): JSX.Element => {
|
||||
return (
|
||||
<div className="paneMainContent">
|
||||
<div className="renewUploadItemsHeader">
|
||||
<span> Select JSON Files </span>
|
||||
<span className="infoTooltip" role="tooltip" tabIndex={0}>
|
||||
<img className="infoImg" src={InfoBubbleIcon} alt="More information" />
|
||||
<span className="tooltiptext infoTooltipWidth">
|
||||
Select one or more JSON files to upload. Each file can contain a single JSON document or an array of JSON
|
||||
documents. The combined size of all files in an individual upload operation must be less than 2 MB. You
|
||||
can perform multiple upload operations for larger data sets.
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
className="importFilesTitle"
|
||||
type="text"
|
||||
disabled
|
||||
value={this.selectedFilesTitle}
|
||||
aria-label="Select JSON Files"
|
||||
/>
|
||||
<input
|
||||
type="file"
|
||||
id="importDocsInput"
|
||||
title="Upload Icon"
|
||||
multiple
|
||||
accept="application/json"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{ display: "none" }}
|
||||
onChange={this.updateSelectedFiles}
|
||||
/>
|
||||
<IconButton
|
||||
iconProps={{ iconName: "FolderHorizontal" }}
|
||||
className="fileImportButton"
|
||||
alt="Select JSON files to upload"
|
||||
title="Select JSON files to upload"
|
||||
onClick={this.onImportButtonClick}
|
||||
onKeyPress={this.onImportButtonKeyPress}
|
||||
/>
|
||||
<div className="fileUploadSummaryContainer" hidden={this.uploadFileData.length === 0}>
|
||||
<b>File upload status</b>
|
||||
<table className="fileUploadSummary">
|
||||
<thead>
|
||||
<tr className="fileUploadSummaryHeader fileUploadSummaryTuple">
|
||||
<th>FILE NAME</th>
|
||||
<th>STATUS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.uploadFileData.map(
|
||||
(data: UploadDetailsRecord): JSX.Element => {
|
||||
return (
|
||||
<tr className="fileUploadSummaryTuple" key={data.fileName}>
|
||||
<td>{data.fileName}</td>
|
||||
<td>{this.fileUploadSummaryText(data.numSucceeded, data.numFailed)}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
private updateSelectedFiles = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
this.selectedFiles = event.target.files;
|
||||
this._updateSelectedFilesTitle();
|
||||
this.triggerRender();
|
||||
};
|
||||
|
||||
private _updateSelectedFilesTitle = (): void => {
|
||||
this.selectedFilesTitle = "";
|
||||
|
||||
if (!this.selectedFiles || this.selectedFiles.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.selectedFiles.length; i++) {
|
||||
this.selectedFilesTitle += `"${this.selectedFiles.item(i).name}"`;
|
||||
}
|
||||
};
|
||||
|
||||
private _totalFileSizeForFileList(): number {
|
||||
let totalFileSize = 0;
|
||||
if (!this.selectedFiles) {
|
||||
return totalFileSize;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.selectedFiles.length; i++) {
|
||||
totalFileSize += this.selectedFiles.item(i).size;
|
||||
}
|
||||
|
||||
return totalFileSize;
|
||||
}
|
||||
|
||||
private fileUploadSummaryText = (numSucceeded: number, numFailed: number): string => {
|
||||
return `${numSucceeded} items created, ${numFailed} errors`;
|
||||
};
|
||||
|
||||
private onImportButtonClick = (): void => {
|
||||
document.getElementById("importDocsInput").click();
|
||||
};
|
||||
|
||||
private onImportButtonKeyPress = (event: React.KeyboardEvent<HTMLButtonElement>): void => {
|
||||
if (event.charCode === Constants.KeyCodes.Enter || event.charCode === Constants.KeyCodes.Space) {
|
||||
this.onImportButtonClick();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
private reset = (): void => {
|
||||
this.isOpened = false;
|
||||
this.isExecuting = false;
|
||||
this.formError = "";
|
||||
this.formErrorDetail = "";
|
||||
this.selectedFiles = undefined;
|
||||
this.selectedFilesTitle = "";
|
||||
this.uploadFileData = [];
|
||||
};
|
||||
}
|
|
@ -965,7 +965,10 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen
|
|||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
const focusElement = document.getElementById("itemImportLink");
|
||||
selectedCollection && container.uploadItemsPane.open();
|
||||
const uploadItemsPane = container.isRightPanelV2Enabled()
|
||||
? container.uploadItemsPaneAdapter
|
||||
: container.uploadItemsPane;
|
||||
selectedCollection && uploadItemsPane.open();
|
||||
focusElement && focusElement.focus();
|
||||
},
|
||||
commandButtonLabel: label,
|
||||
|
|
|
@ -431,7 +431,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- Global loader - End -->
|
||||
|
||||
<div data-bind="react:uploadItemsPaneAdapter"></div>
|
||||
<add-database-pane params="{data: addDatabasePane}"></add-database-pane>
|
||||
<add-collection-pane params="{data: addCollectionPane}"></add-collection-pane>
|
||||
<delete-collection-confirmation-pane params="{data: deleteCollectionConfirmationPane}">
|
||||
|
|
Loading…
Reference in New Issue